Initial commit

This commit is contained in:
Trevor Vallender 2024-01-20 14:39:54 +00:00
commit 129a4ecbc9
228 changed files with 18680 additions and 0 deletions

6
README.md Normal file
View File

@ -0,0 +1,6 @@
# Books
Code from programming books I work through—both sample code from the books and code
I write myself.
## Advanced Programming in the UNIX environment

BIN
apitue/01/simple_shell Executable file

Binary file not shown.

44
apitue/01/simple_shell.c Normal file
View File

@ -0,0 +1,44 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
char * get_input(char *buffer, size_t buflen) {
printf("$$ ");
return fgets(buffer, buflen, stdin);
}
int main(int argc, char **argv) {
char buf[BUFSIZ];
pid_t pid;
int status;
// Cast to void to prevent compiler warning
(void)argc;
(void)argv;
while(get_input(buf, sizeof(buf))) {
buf[strlen(buf) - 1] = '\0';
if ((pid = fork()) == -1) {
fprintf(stderr, "SHELL: Cant fork: %s\n", strerror(errno));
continue;
} else if (pid == 0) {
execlp(buf, buf, (char *)0);
fprintf(stderr, "SHELL: Cant exec %s: %s\n", buf, strerror(errno));
exit(EX_UNAVAILABLE);
}
// Parent waits
if ((pid = waitpid(pid, &status, 0)) < 0) {
fprintf(stderr, "SHELL: waitpid error: %s\n", strerror(errno));
}
}
exit(EX_OK);
}

View File

@ -0,0 +1,26 @@
# This file is part of the sample code and exercises
# used by the class "Advanced Programming in the UNIX
# Environment" taught by Jan Schaumann
# <jschauma@netmeister.org> at Stevens Institute of
# Technology.
#
# This file is in the public domain.
#
# You don't have to, but if you feel like
# acknowledging where you got this code, you may
# reference me by name, email address, or point
# people to the course website:
# https://stevens.netmeister.org/631/
#! /bin/sh
set -eu
umask 022
for set in gnusrc sharesrc src syssrc; do
echo "Fetching ${set}..."
ftp -V ftp.netbsd.org:/pub/NetBSD/NetBSD-9.3/source/sets/${set}.tgz
echo "Extracting ${set}..."
su root -c "tar zxf ${set}.tgz -C /"
rm -f "${set}.tgz"
done

View File

@ -0,0 +1,26 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
/* cast to void to suppress compiler warnings about unused variables */
(void)argc;
(void)argv;
printf("Hello, World!\n");
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,28 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This trivial program simply prints out its own PID and exits.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main() {
printf("Our process id is %d.\n", getpid());
return(EXIT_SUCCESS);
}

View File

@ -0,0 +1,57 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* Stripped down version of 'cat', using unbuffered I/O.
* ./simple-cat < simple-cat.c
*
* Guess what, this is also a primitive version of 'cp':
* ./simple-cat <simple-cat.c >simple-cat.copy
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef BUFFSIZE
#define BUFFSIZE 32768
#endif
int
main(int argc, char **argv) {
int n;
char buf[BUFFSIZE];
/* cast to void to silence compiler warnings */
(void)argc;
(void)argv;
while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) {
if (write(STDOUT_FILENO, buf, n) != n) {
fprintf(stderr, "Unable to write: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
}
if (n < 0) {
fprintf(stderr, "Unable to read: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
}

View File

@ -0,0 +1,51 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* Stripped down version of 'cat', buffered version.
* Guess what, this is also a primitive version of 'cp':
* ./simple-cat <simple-cat.c >simple-cat.copy
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char **argv) {
int c;
/* cast to void to silence compiler warnings */
(void)argc;
(void)argv;
while ((c = getc(stdin)) != EOF) {
if (putc(c, stdout) == EOF) {
fprintf(stderr, "Unable to write: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
}
if (ferror(stdin)) {
fprintf(stderr, "Unable to read: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
}

View File

@ -0,0 +1,53 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* simple-ls.c
* Extremely low-power ls clone.
* ./simple-ls .
*/
#include <sys/types.h>
#include <errno.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "usage: %s dir_name\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((dp = opendir(argv[1])) == NULL) {
fprintf(stderr, "Unable to open '%s': %s\n",
argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
while ((dirp = readdir(dp)) != NULL) {
printf("%s\n", dirp->d_name);
}
(void)closedir(dp);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,76 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* World's simplest shell.
* Loops, reads input and tries to execute it.
* Note: no tokenization, can be ^C'd, but does look at PATH
*
* ./simple-shell
* $$ ls
* $$ ls -l # error
* $$ ^C
*
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
char *
getinput(char *buffer, size_t buflen) {
printf("$$ ");
return fgets(buffer, buflen, stdin);
}
int
main(int argc, char **argv) {
char buf[BUFSIZ];
pid_t pid;
int status;
/* cast to void to silence compiler warnings */
(void)argc;
(void)argv;
while (getinput(buf, sizeof(buf))) {
buf[strlen(buf) - 1] = '\0';
if((pid=fork()) == -1) {
fprintf(stderr, "shell: can't fork: %s\n",
strerror(errno));
continue;
} else if (pid == 0) { /* child */
execlp(buf, buf, (char *)0);
fprintf(stderr, "shell: couldn't exec %s: %s\n", buf,
strerror(errno));
exit(EX_UNAVAILABLE);
}
/* parent waits */
if ((pid=waitpid(pid, &status, 0)) < 0) {
fprintf(stderr, "shell: waitpid error: %s\n",
strerror(errno));
}
}
exit(EX_OK);
}

View File

@ -0,0 +1,83 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* World's 2nd simplest shell
* Same as simple-shell.c, but with a SIGINT signal handler.
* Feed EOF (^D) to exit.
*
* Also illustrates forward declaration of a function prototype.
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
char *
getinput(char *buffer, size_t buflen) {
printf("$$ ");
return fgets(buffer, buflen, stdin);
}
void
sig_int(int signo) {
printf("\nCaught SIGINT (Signal #%d)!\n$$ ", signo);
(void)fflush(stdout);
}
int
main(int argc, char **argv) {
char buf[BUFSIZ];
pid_t pid;
int status;
/* cast to void to silence compiler warnings */
(void)argc;
(void)argv;
if (signal(SIGINT, sig_int) == SIG_ERR) {
fprintf(stderr, "signal error: %s\n", strerror(errno));
exit(1);
}
while (getinput(buf, sizeof(buf))) {
buf[strlen(buf) - 1] = '\0';
if((pid=fork()) == -1) {
fprintf(stderr, "shell: can't fork: %s\n",
strerror(errno));
continue;
} else if (pid == 0) { /* child */
execlp(buf, buf, (char *)0);
fprintf(stderr, "shell: couldn't exec %s: %s\n", buf,
strerror(errno));
exit(EX_UNAVAILABLE);
}
/* parent waits */
if ((pid=waitpid(pid, &status, 0)) < 0) {
fprintf(stderr, "shell: waitpid error: %s\n",
strerror(errno));
}
}
exit(EX_OK);
}

View File

@ -0,0 +1,21 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
int
main() {
printf("Welcome to CS631 Advanced Programming in the UNIX Environment, %s!\n", getlogin())
}

View File

@ -0,0 +1,39 @@
catio: tmpfiles simple-cat.c
@i=0; for n in 3145728 1048576 32768 16384 4096 1024 256 128 64 1; do \
echo "BUFFSIZE = $$n"; \
cc -Wall -DBUFFSIZE=$$n simple-cat.c; \
i=$$(( $$i + 1 )); \
for j in $$(jot 5); do \
time ./a.out <tmp/file$$i >tmp/out; \
done; \
echo; \
echo; \
done;
clean:
rm -fr tmp
tmpfiles: tmp/file9
tmp/file9:
@mkdir -p tmp
@for n in $$(jot 10); do \
echo "Creating file number $$n..."; \
dd if=/dev/urandom of=tmp/file$$n bs=$$(( 1024 * 1024 )) count=100 2>/dev/null;\
done;
sync: tmpfiles scat
time ./scat <tmp/file9 >out
scat: sync-cat.c
cc -Wall sync-cat.c -o scat
async: tmpfiles ascat
time ./ascat <tmp/file9 >out
ascat: async-cat.c
cc -Wall $? -o $@
async-cat.c: sync-cat.c
sed -e 's|\(.*O_SYNC.*\)|//\1|' sync-cat.c > async-cat.c

View File

@ -0,0 +1,49 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* A simple program to show what arguments were passed to a program. This
* can be used to illustrate how different shells expand arguments
* differently.
*
* See also:
* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
* https://wpollock.com/ShScript/CmdLineProcessing.htm
*
* Examples:
* ./a.out
* ./a.out *.c
* ./a.out *.none
* ./a.out *.[1c]
* ./a.out "*.c"
* ./a.out $USER
* ./a.out "$(echo *.1)"
* ./a.out {foo,bar,baz}.whatever
* ./a.out {1..5}
* ./a.out {1..5}{a..f}
*/
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char **argv) {
int i;
for (i=0; i<argc; i++) {
printf("%s\n", argv[i]);
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,56 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This program illustrates that you an close the default
* standard I/O filedescriptors. To reopen, you then need
* to explicitly open the terminal device and dup(2) the
* descriptor onto it.
*/
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main() {
int fd;
if ((fd = open("/dev/tty", O_WRONLY)) < 0) {
err(EXIT_FAILURE, "Unable to open /dev/tty");
/* NOTREACHED */
}
(void)printf("Opened /dev/tty on fd#%d.\n", fd);
(void)printf("Closing STDERR_FILENO...\n");
(void)close(STDERR_FILENO);
(void)fprintf(stderr, "This message will not be shown.\n");
if (dup2(fd, STDERR_FILENO) < 0) {
/* stderr is still closed */
(void)fprintf(stdout, "Unable to dup2: %s\n", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
(void)fprintf(stderr, "Error messages back to normal.\n");
(void)close(fd);
return EXIT_SUCCESS;
}

249
apitue/sample-code/02/dump Normal file
View File

@ -0,0 +1,249 @@
173 1 ktrace EMUL "netbsd"
173 1 ktrace CALL execve(0x7f7fff6c5140,0x7f7fff6c5648,0x7f7fff6c5658)
173 1 ktrace NAMI "/home/jschauma/bin/ls"
173 1 ktrace RET execve -1 errno 2 No such file or directory
173 1 ktrace CALL execve(0x7f7fff6c5140,0x7f7fff6c5648,0x7f7fff6c5658)
173 1 ktrace NAMI "/bin/ls"
173 1 ktrace NAMI "/libexec/ld.elf_so"
173 1 ls EMUL "netbsd"
173 1 ls RET execve JUSTRETURN
173 1 ls CALL mmap(0,0x8000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597951066112/0x7981b26a8000
173 1 ls CALL open(0x7f7e4ae0d39f,0,0x7f7e4b012768)
173 1 ls NAMI "/etc/ld.so.conf"
173 1 ls RET open -1 errno 2 No such file or directory
173 1 ls CALL open(0x7f7fff4c7e68,0,1)
173 1 ls NAMI "/lib/libutil.so.7"
173 1 ls RET open 3
173 1 ls CALL __fstat50(3,0x7f7fff4c7d68)
173 1 ls RET __fstat50 0
173 1 ls CALL mmap(0,0x1000,PROT_READ,0x1<SHARED,FILE,ALIGN=NONE>,3,0,0)
173 1 ls RET mmap 133597951062016/0x7981b26a7000
173 1 ls CALL munmap(0x7981b26a7000,0x1000)
173 1 ls RET munmap 0
173 1 ls CALL mmap(0,0x21d000,PROT_READ|PROT_EXEC,0x15000002<PRIVATE,FILE,ALIGN=2MB>,3,0,0)
173 1 ls RET mmap 133597948280832/0x7981b2400000
173 1 ls CALL mmap(0x7981b2617000,0x4000,PROT_READ|PROT_WRITE,0x12<PRIVATE,FIXED,FILE,ALIGN=NONE>,3,0,0x17000)
173 1 ls RET mmap 133597950472192/0x7981b2617000
173 1 ls CALL mmap(0x7981b261b000,0x2000,PROT_READ|PROT_WRITE,0x1012<PRIVATE,FIXED,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950488576/0x7981b261b000
173 1 ls CALL mprotect(0x7981b2417000,0x200000,PROT_NONE)
173 1 ls RET mprotect 0
173 1 ls CALL close(3)
173 1 ls RET close 0
173 1 ls CALL open(0x7f7fff4c7e68,0,7)
173 1 ls NAMI "/lib/libc.so.12"
173 1 ls RET open 3
173 1 ls CALL __fstat50(3,0x7f7fff4c7d68)
173 1 ls RET __fstat50 0
173 1 ls CALL mmap(0,0x1000,PROT_READ,0x1<SHARED,FILE,ALIGN=NONE>,3,0,0)
173 1 ls RET mmap 133597951062016/0x7981b26a7000
173 1 ls CALL munmap(0x7981b26a7000,0x1000)
173 1 ls RET munmap 0
173 1 ls CALL mmap(0,0x5e2000,PROT_READ|PROT_EXEC,0x15000002<PRIVATE,FILE,ALIGN=2MB>,3,0,0)
173 1 ls RET mmap 133597941989376/0x7981b1e00000
173 1 ls CALL mmap(0x7981b21ae000,0x12000,PROT_READ|PROT_WRITE,0x12<PRIVATE,FIXED,FILE,ALIGN=NONE>,3,0,0x1ae000)
173 1 ls RET mmap 133597945847808/0x7981b21ae000
173 1 ls CALL mmap(0x7981b21c0000,0x222000,PROT_READ|PROT_WRITE,0x1012<PRIVATE,FIXED,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597945921536/0x7981b21c0000
173 1 ls CALL mprotect(0x7981b1faf000,0x1ff000,PROT_NONE)
173 1 ls RET mprotect 0
173 1 ls CALL close(3)
173 1 ls RET close 0
173 1 ls CALL mprotect(0x7981b2617000,0x2000,PROT_READ)
173 1 ls RET mprotect 0
173 1 ls CALL mprotect(0x7981b21ae000,0xc000,PROT_READ)
173 1 ls RET mprotect 0
173 1 ls CALL mprotect(0x45605000,0x1000,PROT_READ)
173 1 ls RET mprotect 0
173 1 ls CALL _lwp_setprivate(0x7981b26ae850)
173 1 ls RET _lwp_setprivate 0
173 1 ls CALL _lwp_self
173 1 ls RET _lwp_self 1
173 1 ls CALL __sigprocmask14(1,0x7f7fff4c8560,0x7f7fff4c85e0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL __sigprocmask14(3,0x7f7fff4c85e0,0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL readlink(0x7981b1f75420,0x7f7fff4c8040,0x400)
173 1 ls NAMI "/etc/malloc.conf"
173 1 ls RET readlink -1 errno 2 No such file or directory
173 1 ls CALL issetugid
173 1 ls RET issetugid 0
173 1 ls CALL __sysctl(0x7f7fff4c83d8,2,0x7981b21d16a0,0x7f7fff4c83d0,0,0)
173 1 ls RET __sysctl 0
173 1 ls CALL mmap(0,0x1000,PROT_NONE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597951062016/0x7981b26a7000
173 1 ls CALL madvise(0x7981b26a7000,0x1000,6)
173 1 ls RET madvise 0
173 1 ls CALL munmap(0x7981b26a7000,0x1000)
173 1 ls RET munmap 0
173 1 ls CALL mmap(0,0x200000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597939892224/0x7981b1c00000
173 1 ls CALL __clock_gettime50(3,0x7f7fff4c83d0)
173 1 ls RET __clock_gettime50 0
173 1 ls CALL __clock_gettime50(3,0x7f7fff4c83d0)
173 1 ls RET __clock_gettime50 0
173 1 ls CALL __clock_gettime50(3,0x7f7fff4c83f0)
173 1 ls RET __clock_gettime50 0
173 1 ls CALL mmap(0,0x8000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597951033344/0x7981b26a0000
173 1 ls CALL mmap(0,0x400000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597935697920/0x7981b1800000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597951029248/0x7981b269f000
173 1 ls CALL __sysctl(0x7f7fff4c8470,2,0x7f7fff4c8450,0x7f7fff4c8448,0,0)
173 1 ls RET __sysctl 0
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597951025152/0x7981b269e000
173 1 ls CALL __sysctl(0x7981b1f7b720,2,0x7981b21d0680,0x7f7fff4c84a8,0,0)
173 1 ls RET __sysctl 0
173 1 ls CALL _lwp_self
173 1 ls RET _lwp_self 1
173 1 ls CALL __sigprocmask14(1,0x7f7fff4c84b0,0x7f7fff4c85e0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL __sigprocmask14(3,0x7f7fff4c85e0,0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL _lwp_self
173 1 ls RET _lwp_self 1
173 1 ls CALL __sigprocmask14(1,0x7f7fff4c84b0,0x7f7fff4c85e0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL __sigprocmask14(3,0x7f7fff4c85e0,0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL issetugid
173 1 ls RET issetugid 0
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597951021056/0x7981b269d000
173 1 ls CALL ioctl(1,TIOCGETA,0x7f7fff4c8580)
173 1 ls GIO fd 1 read 44 bytes
"\^B+\0\0\a\0\0\0\0K\0\0\M-K\^E\0 \^D\M^?\M^?\^?\^W\^U\^R\M^?\^C\^\\^Z\
\^Y\^Q\^S\^V\^O\^A\0\^T\M^?\M^@%\0\0\M^@%\0\0"
173 1 ls RET ioctl 0
173 1 ls CALL ioctl(1,TIOCGWINSZ,0x7f7fff4c85d8)
173 1 ls GIO fd 1 read 8 bytes
"\^X\0P\0p\^C\^P\^B"
173 1 ls RET ioctl 0
173 1 ls CALL getuid
173 1 ls RET getuid 1000/0x3e8, 1000/0x3e8
173 1 ls CALL mmap(0,0x5000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597951000576/0x7981b2698000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950996480/0x7981b2697000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950992384/0x7981b2696000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950988288/0x7981b2695000
173 1 ls CALL __stat50(0x7981b269d0f0,0x7f7fff4c8470)
173 1 ls NAMI "."
173 1 ls RET __stat50 0
173 1 ls CALL open(0x7981b1f7877e,0x400000,0)
173 1 ls NAMI "."
173 1 ls RET open 3
173 1 ls CALL fchdir(3)
173 1 ls RET fchdir 0
173 1 ls CALL open(0x7981b1f7877e,0x400000,0)
173 1 ls NAMI "."
173 1 ls RET open 4
173 1 ls CALL open(0x7981b2697000,0x600004,0)
173 1 ls NAMI "."
173 1 ls RET open 5
173 1 ls CALL fstatvfs1(5,0x7f7fff4c7b80,2)
173 1 ls RET fstatvfs1 0
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950984192/0x7981b2694000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950980096/0x7981b2693000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950976000/0x7981b2692000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950971904/0x7981b2691000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950967808/0x7981b2690000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950963712/0x7981b268f000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950959616/0x7981b268e000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950955520/0x7981b268d000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950951424/0x7981b268c000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950947328/0x7981b268b000
173 1 ls CALL mmap(0,0x1000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950943232/0x7981b268a000
173 1 ls CALL lseek(5,0,0,1)
173 1 ls RET lseek 0
173 1 ls CALL __getdents30(5,0x7981b2694000,0x1000)
173 1 ls GIO fd 5 read 408 bytes
"\^O0\^V\0\0\0\0\0\^P\0\^A\0\^D.\0\0\v0\^V\0\0\0\0\0\^P\0\^B\0\^D..\0\
\M^Q0\^V\0\0\0\0\0\^X\0\^E\0\bfds.c\0\0\0\0\0\0\M^R0\^V\0\0\0\0\0\^X\0\
\^F\0\bhole.c\0\0\0\0\0\M^S0\^V\0\0\0\0\0\^X\0\b\0\bMakefile\0\0\0\M^T\
0\^V\0\0\0\0\0\^X\0\n\0\bsync-cat.c\0\M^U0\^V\0\0\0\0\0\^X\0\^F\0\brwe\
x.c\0\0\0\0\0\M^V0\^V\0\0\0\0\0\^X\0\a\0\bredir.c\0\0\0\0\M^W0\^V\0\0\
\0\0\0\^X\0\a\0\blseek.c\0\0\0\0\M^X0\^V\0\0\0\0\0 \0\f\0\bsimple-cat.\
c\0\0\0\0\0\0\0\M^Y0\^V\0\0\0\0\0\^X\0\^F\0\bargv.c\0\0\0\0\0\M^Z0\^V\
\0\0\0\0\0\^X\0\b\0\bopenex.c\0\0\0\M^[0\^V\0\0\0\0\0\^X\0 \0\bop\
enfds.c\0\0\M^\0\^V\0\0\0\0\0\^X\0 \0\bopenmax.c\0\0\M-C0\^V\0\0\
\0\0\0\^X\0\^E\0\ba.out\0\0\0\0\0\0\M-f0\^V\0\0\0\0\0 \0\^N\0\blseek-t\
o-end.c\0\0\0\0\0\M-b0\^V\0\0\0\0\0\^X\0\n\0\bktrace.out\0"
173 1 ls RET __getdents30 408/0x198
173 1 ls CALL mmap(0,0x5000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950922752/0x7981b2685000
173 1 ls CALL lseek(5,0,0,1)
173 1 ls RET lseek 512/0x200
173 1 ls CALL __getdents30(5,0x7981b2694000,0x1000)
173 1 ls GIO fd 5 read 0 bytes
""
173 1 ls RET __getdents30 0
173 1 ls CALL close(5)
173 1 ls RET close 0
173 1 ls CALL mmap(0,0x7000,PROT_READ|PROT_WRITE,0x1002<PRIVATE,ANONYMOUS,ALIGN=NONE>,0xffffffff,0,0)
173 1 ls RET mmap 133597950894080/0x7981b267e000
173 1 ls CALL fchdir(4)
173 1 ls RET fchdir 0
173 1 ls CALL close(4)
173 1 ls RET close 0
173 1 ls CALL __fstat50(1,0x7f7fff4c7fb0)
173 1 ls RET __fstat50 0
173 1 ls CALL ioctl(1,TIOCGETA,0x7f7fff4c8020)
173 1 ls GIO fd 1 read 44 bytes
"\^B+\0\0\a\0\0\0\0K\0\0\M-K\^E\0 \^D\M^?\M^?\^?\^W\^U\^R\M^?\^C\^\\^Z\
\^Y\^Q\^S\^V\^O\^A\0\^T\M^?\M^@%\0\0\M^@%\0\0"
173 1 ls RET ioctl 0
173 1 ls CALL write(1,0x7981b2694000,0x47)
173 1 ls GIO fd 1 wrote 71 bytes
"Makefile fds.c lseek-to-end.c openfds.c rwex.c\
\n"
173 1 ls RET write 71/0x47
173 1 ls CALL write(1,0x7981b2694000,0x4d)
173 1 ls GIO fd 1 wrote 77 bytes
"a.out hole.c lseek.c openmax.c simple\
-cat.c\n"
173 1 ls RET write 77/0x4d
173 1 ls CALL write(1,0x7981b2694000,0x4b)
173 1 ls GIO fd 1 wrote 75 bytes
"argv.c ktrace.out openex.c redir.c sync-c\
at.c\n"
173 1 ls RET write 75/0x4b
173 1 ls CALL fchdir(3)
173 1 ls RET fchdir 0
173 1 ls CALL close(3)
173 1 ls RET close 0
173 1 ls CALL _lwp_self
173 1 ls RET _lwp_self 1
173 1 ls CALL __sigprocmask14(1,0x7f7fff4c8570,0x7f7fff4c85b0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL __sigprocmask14(3,0x7f7fff4c85b0,0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL _lwp_self
173 1 ls RET _lwp_self 1
173 1 ls CALL __sigprocmask14(1,0x7f7fff4c84c0,0x7f7fff4c85b0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL __sigprocmask14(3,0x7f7fff4c85b0,0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL _lwp_self
173 1 ls RET _lwp_self 1
173 1 ls CALL __sigprocmask14(1,0x7f7fff4c84c0,0x7f7fff4c85b0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL __sigprocmask14(3,0x7f7fff4c85b0,0)
173 1 ls RET __sigprocmask14 0
173 1 ls CALL exit(0)

View File

@ -0,0 +1,85 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* A program to show the value of some file
* descriptors.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main() {
int fd1, fd2, fd3;
FILE *f;
printf("STDIN_FILENO: %d\n", STDIN_FILENO);
printf("stdin: %d\n", fileno(stdin));
printf("STDOUT_FILENO: %d\n", STDOUT_FILENO);
printf("stdout: %d\n", fileno(stdout));
printf("STDERR_FILENO: %d\n", STDERR_FILENO);
printf("stderr: %d\n", fileno(stderr));
printf("\nOpening /dev/zero...\n");
if ((fd1 = open("/dev/zero", O_RDONLY)) < 0) {
fprintf(stderr, "Unable to open /dev/zero: %s\n", strerror(errno));
} else {
printf("fd1: %d\n", fd1);
}
printf("\nOpening /dev/zero a second time...\n");
if ((fd2 = open("/dev/zero", O_RDONLY)) < 0) {
fprintf(stderr, "Unable to open /dev/zero: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("fd2: %d\n", fd2);
printf("\nNow closing fd1, but keeping fd2 open..\n");
(void)close(fd1);
printf("\nOpening /dev/zero a third time...\n");
if ((fd3 = open("/dev/zero", O_RDONLY)) < 0) {
fprintf(stderr, "Unable to open /dev/zero: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("fd3: %d\n", fd3);
printf("\nNow closing fd2 and fd3.\n");
(void)close(fd2);
(void)close(fd3);
printf("Now opening /dev/zero as a stream.\n");
if ((f = fopen("/dev/zero", "r")) == NULL) {
fprintf(stderr, "Unable to open /dev/zero: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("f: %d\n", fileno(f));
(void)fclose(f);
(void)close(STDERR_FILENO);
printf("\nOpening /dev/stderr after closing STDERR...\n");
if ((fd3 = open("/dev/stderr", O_RDONLY)) < 0) {
fprintf(stdout, "Unable to open /dev/stderr: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("stderr is now: %d\n", fd3);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,64 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This simple program creates a file with a hole in it, a so-called
* sparse file. Use hexdump(1) or od(1) to verify that there is no data
* in between the two strings; then copy the file to to another and
* observe that the kernel supplied zeros to fill the hole.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";
#define BIGNUM 10240000
int
main(void) {
int fd;
if ((fd = creat("file.hole", S_IRUSR | S_IWUSR)) < 0) {
perror("creat error");
return EXIT_FAILURE;
}
if (write(fd, buf1, strlen(buf1)) != sizeof(buf1) - 1) {
perror("error writing buf1");
return EXIT_FAILURE;
}
if (lseek(fd, BIGNUM, SEEK_CUR) == -1) {
perror("lseek error");
return EXIT_FAILURE;
}
if (write(fd, buf2, strlen(buf2)) != sizeof(buf2) - 1) {
perror("error writing buf2");
return EXIT_FAILURE;
}
sleep(30);
(void)close(fd);
return EXIT_SUCCESS;
}

Binary file not shown.

View File

@ -0,0 +1,73 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This program creates a new file, writes ten bytes to it
* and then seeks to the end of the file. Where do we end up?
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DATA "0123456789"
void
printOffset(int fd, int whence) {
off_t off;
if ((off = lseek(fd, 0, whence)) == -1) {
err(EXIT_FAILURE, "Unable to lseek");
/* NOTREACHED */
}
(void)printf("Offset: %d\n", (int)off);
}
int
main(void) {
int fd;
int len;
if ((fd = open("f", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) == -1) {
err(EXIT_FAILURE, "Unable create file 'f'");
/* NOTREACHED */
}
printOffset(fd, SEEK_CUR);
len = sizeof(DATA) - 1;
if (write(fd, DATA, len) != len) {
err(EXIT_FAILURE, "Unable write");
/* NOTREACHED */
}
printOffset(fd, SEEK_CUR);
printOffset(fd, SEEK_END);
(void)close(fd);
if (unlink("f") < 0) {
err(EXIT_FAILURE, "Unable to unlink 'f'");
/* NOTREACHED */
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,35 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This trivial program verifies whether or not STDIN is seekable. Test
* on a regular file, on a pipe or a fifo.
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(void) {
if (lseek(STDIN_FILENO, 0, SEEK_CUR) == -1 )
printf("cannot seek\n");
else
printf("seek OK\n");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,162 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This program illustrates the usefulness of openat(2) to avoid
* certain race conditions:
*
* Assume that you want to open the files "file1" and "file2" found
* in the directory "../dir". You might start out using
*
* fd1 = open("../dir/file1", ...)
* fd2 = open("../dir/file2", ...)
*
* However, in between these two calls, another process might have
* renamed the directory "../dir" to "../dir2", then created "../dir"
* and placed a different file named "file2" into it. Your program
* now has opened two files from two different directories.
*
* With openat(2), you could guarantee that the call to open "file2"
* will use the same directory as the call to open "file1":
*
* dfd = open("../dir/", O_DIRECTORY ...)
* fd1 = openat(dfd, "file1", ...)
* fd2 = openat(dfd, "file2", ...)
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void
readData(int fd) {
int n;
char buf[BUFSIZ];
bzero(buf, BUFSIZ);
if ((n = read(fd, buf, BUFSIZ)) == -1) {
(void)fprintf(stderr, "Unable to read data from fd %d: %s\n",
fd, strerror(errno));
exit(EXIT_FAILURE);
}
(void)printf("Read data: %s", buf);
}
void
readFileUsingOpenat(const int dfd, const char *f) {
int fd;
(void)printf("Opening '%s' using openat(2)...\n", f);
if ((fd = openat(dfd, f, O_RDONLY)) == -1) {
(void)fprintf(stderr, "Unable to open '%s': %s\n",
f, strerror(errno));
exit(EXIT_FAILURE);
}
readData(fd);
}
void
readFileUsingOpen(const char *f) {
int fd;
(void)printf("Opening '%s'...\n", f);
if ((fd = open(f, O_RDONLY)) == -1) {
(void)fprintf(stderr, "Unable to open '%s': %s\n",
f, strerror(errno));
exit(EXIT_FAILURE);
}
readData(fd);
}
void
reset() {
system("rm -fr ../dir");
system("mv ../dir2 ../dir");
}
void
makeFiles() {
}
void
setup() {
/* Trivial setup via system(3) because we're lazy. */
system("mkdir -p ./t ./dir");
system("echo file1 > ./dir/file1");
system("echo file2 > ./dir/file2");
if (chdir("./t") < 0) {
(void)fprintf(stderr, "Unable to cd to './t': %s\n", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
}
void
simulateRaceCondition() {
(void)printf("Simulating race condition by renaming '../dir'...\n");
system("mv ../dir ../dir2");
system("mkdir ../dir");
system("echo notfile2 > ../dir/file2");
}
void
cleanup() {
if (chdir("..") < 0) {
(void)fprintf(stderr, "Unable to register exit handler: %s\n",
strerror(errno));
} else {
system("rm -fr t dir dir2");
}
}
int
main() {
if (atexit(cleanup) < 0) {
(void)fprintf(stderr, "Unable to register exit handler: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
setup();
readFileUsingOpen("../dir/file1");
simulateRaceCondition();
readFileUsingOpen("../dir/file2");
reset();
(void)printf("\nLet's try again...\n\n");
int dfd;
if ((dfd = open("../dir", O_RDONLY | O_DIRECTORY)) == -1) {
(void)fprintf(stderr, "Unable to open directory '../dir': %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
readFileUsingOpenat(dfd, "file1");
simulateRaceCondition();
readFileUsingOpenat(dfd, "file2");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,170 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This trivial program illustrates how to open files. We present the
* following use cases:
*
* - create a non-existent file
* - "create" an existing file
* - fail to create an existing file
* - open an existing file
* - fail to open a non-existing file
* - truncate an existing file
*/
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef SLEEP
#define SLEEP 10
#endif
void
createFile() {
int fd;
printf("Checking if './newfile' exists...\n");
system("ls -l ./newfile");
printf("Trying to create './newfile' with O_RDONLY | O_CREAT...\n");
if ((fd = open("./newfile", O_RDONLY | O_CREAT,
S_IRUSR | S_IWUSR)) == -1) {
fprintf(stderr, "Unable to create './newfile': %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
printf("'./newfile' created. File descriptor is: %d\n", fd);
/* We are leaking a file descriptor here to illustrate that they
* are increasing as we open more files. Normally, we would call
* close(2) whenever we're done using the decriptor. */
}
void
failExclFileCreation() {
int fd;
printf("Checking if './newfile' exists...\n");
system("ls -l ./newfile");
printf("Trying to create './newfile' with O_RDONLY | O_CREAT | O_EXCL...\n");
if ((fd = open("./newfile", O_RDONLY | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR)) == -1) {
fprintf(stderr, "Unable to create './newfile': %s\n",
strerror(errno));
}
/* We expect this to fail! */
if (close(fd) == -1) {
fprintf(stderr, "Closing failed: %s\n", strerror(errno));
}
}
void
failOpenNonexistingFile() {
int fd;
printf("Trying to open (non-existant) './nosuchfile' with O_RDONLY...\n");
if ((fd = open("./nosuchfile", O_RDONLY)) == -1) {
fprintf(stderr, "Unable to open './nosuchfile': %s\n",
strerror(errno));
}
/* We know this is going to fail, but no need to complain. */
(void)close(fd);
}
void
openFile() {
int fd;
printf("Trying to open './openex.c' with O_RDONLY...\n");
if ((fd = open("./openex.c", O_RDONLY)) == -1) {
fprintf(stderr, "Unable to open './openex.c': %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
printf("'./openex.c' opened. File descriptor is: %d\n", fd);
if (close(fd) == 0) {
printf("'./openex.c' closed again\n");
}
}
void
truncateFile() {
int fd;
system("cp openex.c newfile");
printf("Copied 'openex.c' to 'newfile'.\n");
system("ls -l newfile");
printf("Trying to open './newfile' with O_RDONLY | O_TRUNC...\n");
if ((fd = open("./newfile", O_RDONLY | O_TRUNC)) == -1) {
fprintf(stderr, "Unable to open './newfile': %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
printf("'./newfile' opened. File descriptor is: %d\n", fd);
printf("'./newfile' truncated -- see 'ls -l newfile'\n");
system("ls -l newfile");
(void)close(fd);
}
int
main() {
createFile();
system("ls -l newfile");
printf("\n");
sleep(SLEEP);
createFile();
system("ls -l newfile");
printf("\n");
sleep(SLEEP);
failExclFileCreation();
printf("\n");
sleep(SLEEP);
openFile();
printf("\n");
sleep(SLEEP);
failOpenNonexistingFile();
printf("\n");
sleep(SLEEP);
truncateFile();
return 0;
}

View File

@ -0,0 +1,122 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This trivial program attempts to determine how many
* open files a process can have. It illustrates the
* use of pre-processor directives and sysconf(3) to
* identify a resource that can be changed at system
* run time.
*
* This program also asks getconf(1) and explicitly
* asks getrlimit(2). Look at the source code for
* getconf(1) and sysconf(3) to show how they are
* implemented, as well as manual page and
* implementation of getdtablesize(3).
*
* Run this once, then use 'ulimit -n' to change the
* limit and run again.
*
* If you (as root) set 'ulimit -n unlimited', what
* value will you get? Why?
*
* What happens if you set this limit to, say, 0?
* Why?
*/
#include <sys/resource.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
countOpenFiles(int num) {
struct stat stats;
int count = 0;
for (int i = 0; i < num; i++) {
if (fstat(i, &stats) == 0) {
printf("Currently open: fd #%d (inode %ld)\n", i,
stats.st_ino);
count++;
}
}
return count;
}
void
openFiles(int num) {
int count, fd;
count = countOpenFiles(num);
printf("Currently open files: %d\n", count);
for (int i = count; i <= num ; i++) {
if ((fd = dup(0)) < 0) {
fprintf(stderr, "%d: Unable to dup fd0: %s (%d)\n", i, strerror(errno), errno);
break;
}
}
}
int
main() {
int openmax;
struct rlimit rlp;
#ifdef OPEN_MAX
printf("OPEN_MAX is defined as %d.\n", OPEN_MAX);
#else
printf("OPEN_MAX is not defined on this platform.\n");
#endif
printf("'getconf OPEN_MAX' says: ");
(void)fflush(stdout);
(void)system("getconf OPEN_MAX");
/* see also: getdtablesize(3), notably the HISTORY section */
errno = 0;
if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {
if (errno == 0) {
fprintf(stderr, "sysconf(3) considers _SC_OPEN_MAX unsupported?\n");
} else {
fprintf(stderr, "sysconf(3) error for _SC_OPEN_MAX: %s\n",
strerror(errno));
}
exit(EXIT_FAILURE);
/* NOTREACHED */
}
printf("sysconf(3) says this process can open %d files.\n", openmax);
if (getrlimit(RLIMIT_NOFILE, &rlp) != 0) {
fprintf(stderr, "Unable to get per process rlimit: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
openmax = (int)rlp.rlim_cur;
printf("getrlimit(2) says this process can open %d files.\n", openmax);
printf("Which one is it?\n\n");
openFiles(openmax);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,129 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This trivial program attempts to determine how many
* open files a process can have. It illustrates the
* use of pre-processor directives and sysconf(3) to
* identify a resource that can be changed at system
* run time.
*
* This program also asks getconf(1) and explicitly
* asks getrlimit(2). Look at the source code for
* getconf(1) and sysconf(3) to show how they are
* implemented, as well as manual page and
* implementation of getdtablesize(3).
*
* Run this once, then use 'ulimit -n' to change the
* limit and run again.
*
* If you (as root) set 'ulimit -n unlimited', what
* value will you get? Why?
*
* What happens if you set this limit to, say, 0?
* Why?
*/
#include <sys/resource.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
countOpenFiles(int num) {
struct stat stats;
int count = 0;
for (int i = 0; i < num; i++) {
if (fstat(i, &stats) == 0) {
printf("Currently open: fd #%d (inode %ld)\n", i,
stats.st_ino);
count++;
}
}
return count;
}
void
openFiles(int num) {
int count, fd;
count = countOpenFiles(num);
printf("Currently open files: %d\n", count);
for (int i = count; i <= num ; i++) {
if ((fd = open("/dev/null", O_RDONLY)) < 0) {
if (errno == EMFILE) {
printf("Opened %d additional files, then failed: %s (%d)\n", i - count, strerror(errno), errno);
break;
} else {
fprintf(stderr, "Unable to open '/dev/null' on fd#%d: %s (errno %d)\n",
i, strerror(errno), errno);
break;
}
}
}
}
int
main() {
int openmax;
struct rlimit rlp;
#ifdef OPEN_MAX
printf("OPEN_MAX is defined as %d.\n", OPEN_MAX);
#else
printf("OPEN_MAX is not defined on this platform.\n");
#endif
printf("'getconf OPEN_MAX' says: ");
(void)fflush(stdout);
(void)system("getconf OPEN_MAX");
/* see also: getdtablesize(3), notably the HISTORY section */
errno = 0;
if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {
if (errno == 0) {
fprintf(stderr, "sysconf(3) considers _SC_OPEN_MAX unsupported?\n");
} else {
fprintf(stderr, "sysconf(3) error for _SC_OPEN_MAX: %s\n",
strerror(errno));
}
exit(EXIT_FAILURE);
/* NOTREACHED */
}
printf("sysconf(3) says this process can open %d files.\n", openmax);
if (getrlimit(RLIMIT_NOFILE, &rlp) != 0) {
fprintf(stderr, "Unable to get per process rlimit: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
openmax = (int)rlp.rlim_cur;
printf("getrlimit(2) says this process can open %d files.\n", openmax);
printf("Which one is it?\n\n");
openFiles(openmax);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,65 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This simple program illustrates output redirection via dup(2).
*
* Compare:
* ./a.out
* ./a.out >/dev/null
* ./a.out 2>/dev/null
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define STDOUT_MSG "A message to stdout.\n"
#define STDERR_MSG "A message to stderr.\n"
void
writeBoth(const char *mark) {
int len, marklen;
marklen = strlen(mark);
if (write(STDOUT_FILENO, mark, marklen) != marklen) {
perror("unable to write marker to stdout");
exit(EXIT_FAILURE);
}
len = strlen(STDOUT_MSG);
if (write(STDOUT_FILENO, STDOUT_MSG, len) != len) {
perror("unable to write to stdout");
exit(EXIT_FAILURE);
}
if (write(STDERR_FILENO, STDERR_MSG, len) != len) {
perror("unable to write to stdout");
exit(EXIT_FAILURE);
}
}
int
main() {
writeBoth("before dup2\n");
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
perror("Unable to redirect stderr to stdout");
exit(EXIT_FAILURE);
}
writeBoth("after dup2\n");
}

View File

@ -0,0 +1,72 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* This trivial program illustrates how we might normally read and write
* to a simple file. Here, we simply open the source code file, read the
* first few bytes, then append a comment.
*
* What happens if we do not open with O_APPEND?
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUFFSIZE 64
#define COMMENT "\n/* Just another comment. */\n"
#define SOURCE "./rwex.c"
int
main() {
int fd, n;
int len;
char buf[BUFFSIZE];
if ((fd = open(SOURCE, O_RDWR | O_APPEND)) == -1) {
fprintf(stderr, "Unable to open '%s': %s\n",
SOURCE, strerror(errno));
exit(EXIT_FAILURE);
}
if ((n = read(fd, buf, BUFFSIZE)) > 0) {
if (write(STDOUT_FILENO, buf, n) != n) {
fprintf(stderr, "Unable to write: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
} else if (n == -1) {
fprintf(stderr, "Error reading from %s: %s\n",
SOURCE, strerror(errno));
exit(EXIT_FAILURE);
}
printf("\n\nOk, we read the first %d bytes. Now let's write something.\n", BUFFSIZE);
len = sizeof(COMMENT) - 1;
if (write(fd, COMMENT, len) != len) {
fprintf(stderr, "Unable to write: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
(void)close(fd);
return EXIT_SUCCESS;
}
/* Just another comment. */

View File

@ -0,0 +1,57 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* Stripped down version of 'cat', using unbuffered I/O.
* ./simple-cat < simple-cat.c
*
* Guess what, this is also a primitive version of 'cp':
* ./simple-cat <simple-cat.c >simple-cat.copy
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef BUFFSIZE
#define BUFFSIZE 32768
#endif
int
main(int argc, char **argv) {
int n;
char buf[BUFFSIZE];
/* cast to void to silence compiler warnings */
(void)argc;
(void)argv;
while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) {
if (write(STDOUT_FILENO, buf, n) != n) {
fprintf(stderr, "Unable to write: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
}
if (n < 0) {
fprintf(stderr, "Unable to read: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
}

View File

@ -0,0 +1,79 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* simple-cat.c, O_SYNC version
*
* Use this program to illustrate the use of fcntl(2)
* to set the O_SYNC flag on STDOUT, which we do not
* open ourselves, so can't set that flag on at that
* time.
*
* This also illustrates the difference between
* synchronous and asynchronous I/O:
*
* Create a large enough file:
*
* dd if=/dev/zero of=file bs=$((1024 * 1024)) count=25
*
* Then run this program:
*
* time ./a.out <file >out
*
* Then, comment out the setting of O_SYNC, recompile
* the program and run it again.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFSIZE 512
int
main(int argc, char **argv) {
int n;
char buf[BUFFSIZE];
int flags;
/* cast to void to silence compiler warnings */
(void)argc;
(void)argv;
if ((flags = fcntl(STDOUT_FILENO, F_GETFL, 0)) < 0) {
perror("Can't get file descriptor flags");
exit(EXIT_FAILURE);
}
//flags |= O_SYNC;
if (fcntl(STDOUT_FILENO, F_SETFL, flags) < 0) {
perror("Can't set file descriptor flags");
exit(EXIT_FAILURE);
}
while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0 )
if ( write(STDOUT_FILENO, buf, n) != n ) {
perror("write error");
exit(EXIT_FAILURE);
}
if (n < 0) {
perror("read error");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,59 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* If you create a new file, write, say,
* 10 bytes of data, and then seek to the
* end of the file, where do you end up? Why?
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define WFILE "/tmp/rw"
#define DLEN 10
int
main() {
int fd, n;
char data[DLEN];
bzero(data, DLEN);
if ((fd = open(WFILE, O_RDWR | O_CREAT | O_EXCL, 0700)) == -1) {
fprintf(stderr, "Unable to open '%s': %s\n",
WFILE, strerror(errno));
exit(EXIT_FAILURE);
}
if (write(fd, data, DLEN) != DLEN) {
fprintf(stderr, "Unable to write: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
if ((n = lseek(fd, 0, SEEK_END)) == 0) {
fprintf(stderr, "Unable to seek: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
printf("Seeked to offset %d\n", n);
(void)close(fd);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,46 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This trivial program illustrates the use of access(2). Compile this
* program and run it with /etc/passwd, /etc/master.passwd as arguments;
* then chown and setuid the executable and repeat.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "%s: usage: %s filename\n", argv[0], argv[0]);
exit(EXIT_FAILURE);
}
if (access(argv[1], R_OK) == -1)
printf("access error for %s\n", argv[1]);
else
printf("access ok for %s\n", argv[1]);
if (open(argv[1], O_RDONLY) == -1)
printf("open error for %s\n", argv[1]);
else
printf("open ok for %s\n", argv[1]);
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,51 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This simple program illustrates the use of the chmod(2) system call,
* and how it can be used to set explicit/absolute modes or to selectively
* enable individual modes.
*
* Set your umask to 077, create file and file1, then run this command.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int
main() {
struct stat sbuf;
if (stat("file", &sbuf) == -1) {
perror("can't stat file");
exit(EXIT_FAILURE);
}
/* turn off owner read permissions and turn on setgid */
if (chmod("file", (sbuf.st_mode & ~S_IRUSR) | S_ISGID) == -1) {
perror("can't chmod file");
exit(EXIT_FAILURE);
}
/* set absolute mode to rw-r--r-- */
if (chmod("file1", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
perror("can't chmod file1");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,76 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This simple program illustrates the use of the chown(2) system call:
*
* touch file
* ./a.out
* ls -l file
* sudo ./a.out
* ls -l file
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* We'll see better ways to get a user's UID or a
* group's GID in our next lecture. */
#define FRED 1001
#define USERS_GID 100
#define TTY_GID 4
void
mychown(const char *file, int uid, int gid) {
if (chown(file, uid, gid) < 0) {
fprintf(stderr, "Unable to chown(%s, %d, %d): %s\n",
file, uid, gid, strerror(errno));
} else {
printf("Successfully chowned %s to %d:%d.\n",
file, uid, gid);
}
}
int
main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s file\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Let's try to take ownership of the file.
* That's not really a useful thing to try,
* since either it works out, in which case
* we already owned the file, or it'll fail.
*
* Unless, of course, we're root... */
mychown(argv[1], getuid(), -1);
/* Next, let's try to change ownership to
* Fred. (Don't hold your breath, unless
* you're root.) */
mychown(argv[1], FRED, -1);
/* Next, let's 'chown:users'... */
mychown(argv[1], -1, USERS_GID);
/* ... and let's try 'chown:tty'. */
mychown(argv[1], -1, TTY_GID);
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,48 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This program prints out the amount of space
* required to represent a directory entry in the Unix
* File System per <ufs/ufs/dir.h>.
*
* ./a.out filename
*
* You should be able to determine how many files of a
* given filename length you can create in a directory
* without that directory size increasing.
*
* Note that once a directory size has increased,
* removing files from it will not shrink it again
* (on UFS/FFS).
*/
#include <sys/types.h>
#include <ufs/ufs/dir.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s name\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("%ld\n", UFS_DIRECTSIZ(strlen(argv[1])));
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,91 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* A simple program to illustrate the difference
* between effective and real user IDs.
*
* Compile, then run as user1 and user2:
* user1$ cc myuids.c
* user1$ ./a.out
* user2$ ./a.out
* user1$ chmod u+s a.out
* user1$ ./a.out
* user2$ ./a.out
*
* For a more complete, albeit notably more complex
* illustration of the various uids and the handling
* of saved-setuid bits, see setuid.c and the comments
* and links in there.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void
printUids() {
uid_t ruid = getuid();
uid_t euid = geteuid();
printf("My effective uid is: %d\n", euid);
printf("My real uid is: %d\n", ruid);
}
int
main() {
printUids();
uid_t ruid = getuid();
uid_t euid = geteuid();
if (ruid == euid) {
/* Nothing meaningful to do here. */
exit(EXIT_SUCCESS);
/* NOTREACHED */
}
printf("\nLet's drop elevated privs and set our effective uid to our real uid.\n");
printf("Calling 'seteuid(%d)'...\n", ruid);
if (seteuid(ruid) < 0) {
fprintf(stderr, "Unable to seteuid(%d): %s\n", ruid, strerror(errno));
} else {
printUids();
}
printf("\nBecause we used seteuid(%d) and not setuid(%d), we can get back our earlier euid %d.\n", ruid, ruid, euid);
printf("Calling 'seteuid(%d)'...\n", euid);
if (seteuid(euid) < 0) {
fprintf(stderr, "Unable to seteuid(%d): %s\n", euid, strerror(errno));
} else {
printUids();
}
printf("\nNow let's try to 'setuid(%d)'...\n", ruid);
if (setuid(ruid) < 0) {
fprintf(stderr, "Unable to setuid(%d): %s\n", ruid, strerror(errno));
} else {
printUids();
}
printf("\nNow let's try to gain back our effective uid %d...\n", euid);
printf("Calling 'seteuid(%d)'...\n", euid);
if (seteuid(euid) < 0) {
fprintf(stderr, "Unable to seteuid(%d): %s\n", euid, strerror(errno));
}
printUids();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,229 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This trivial program illustrates the use of
* setuid(2) and seteuid(2). After compiling,
* chmod(1) and chown(1) as needed to access a
* privileged resource (e.g. /etc/sudoers).
*
* Note: this example ignores group IDs. See
* https://is.gd/l6pu5K for details on the
* order of dropping all privileges correctly.
*
* Example invocation:
* cc -Wall setuid.c
* sudo chown root a.out
* sudo chmod 4755 a.out
* ./a.out /etc/sudoers
*
* Note: after chowning, try to recompile. Does
* your compiler overwrite a.out? Why/why not?
*
* Note: setuid is not restricted to setuid-0. Try
* with another user!
*
* mkdir -m 0700 /tmp/daemon
* touch /tmp/daemon/somefile
* chmod a+r /tmp/daemon/somefile
* sudo chown daemon /tmp/daemon
* sudo chown daemon a.out
* sudo chmod 4755 a.out
* ls -l a.out
* ls -l /tmp/daemon
* ls -ld /tmp/daemon
* ./a.out /tmp/daemon/somefile
* ./a.out /etc/sudoers
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define UNPRIVILEGED_UID 1
char buf[BUFSIZ];
uid_t ruid;
uid_t euid;
uid_t suid;
void myseteuid(int);
void printUids(const char *);
/* We're using this wrapper function, because the behavior
* of seteuid(2) with respect to the saved-set-uid is inconsistent
* across platforms. On e.g. NetBSD, the POSIX.1-2017 mandated
* behavior is not implemented; see the note in the manual page
* as well as in <unistd.h>. */
void
myseteuid(int myeuid) {
char *func = "seteuid(";
#ifdef _POSIX_SAVED_IDS
if (seteuid(myeuid) == -1) {
fprintf(stderr, "Unable to seteuid(%d): %s\n", myeuid, strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
#else
if (setreuid(-1, myeuid) == -1) {
fprintf(stderr, "Unable to setreuid(-1, %d): %s\n", myeuid, strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
func = "setreuid(-1, ";
#endif
if (snprintf(buf, BUFSIZ, "After %s%d)", func, myeuid) < 0) {
fprintf(stderr, "Unable to snprintf: %s\n", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
printUids(buf);
}
/* On e.g. Linux, we can get the saved set-uid
* via getresuid(2); not all systems support
* this, however. On those that do not,
* we use the suid value initialized at program
* startup.
*/
void
printUids(const char *msg) {
ruid = getuid();
euid = geteuid();
#ifdef _GNU_SOURCE
if (getresuid(&ruid, &euid, &suid) < 0) {
fprintf(stderr, "Unable to getresuid: %s\n", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
#endif
printf("%s: ruid %d, euid %d, suid %d\n", msg, ruid, euid, suid);
}
int
main(int argc, char **argv) {
int fd;
if (argc != 2) {
fprintf(stderr, "%s: Usage: %s filename\n", argv[0], argv[0]);
exit(EXIT_FAILURE);
/* NOTREACHED */
}
ruid = getuid();
euid = geteuid();
/* fake saved-setuid */
suid = geteuid();
printUids("Program start");
printf("We're privileged; let's set all UIDs to another account.\n");
myseteuid(UNPRIVILEGED_UID);
printf("We're unprivileged, but with the help of the saved set-uid, we can regain initial setuid (%d) privs.\n", suid);
printf("But let's drop them again via seteuid(%d)...\n", ruid);
myseteuid(ruid);
printf("Trying to open a privileged file...\n");
if ((fd = open(argv[1], O_RDONLY)) == -1) {
fprintf(stderr, "Unable to open %s: %s\n",
argv[1], strerror(errno));
}
/* We don't do anything with the file, we just demonstrated
* that we were unable to open it. */
(void)close(fd);
printf("Ok, let's try with elevated privileges.\n");
myseteuid(suid);
if ((fd = open(argv[1], O_RDONLY)) == -1) {
fprintf(stderr, "Unable to open %s: %s\n",
argv[1], strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
} else {
printf("Opening worked.\n");
/* Now we could do stuff with 'fd', if we were
* so inclined. We're not, though. */
(void)close(fd);
}
printf("Alright, we're done using our elevated privileges. Let's drop them permanently.\n");
if (setuid(ruid) == -1) {
fprintf(stderr, "Unable to setuid: %s\n", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
if (snprintf(buf, BUFSIZ, "After setuid(%d)", ruid) < 0) {
fprintf(stderr, "Unable to snprintf: %s\n", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
printUids(buf);
printf("Now trying to gain elevated privileges again.\n");
/* Trying to gain elevated privileges again
* should fail here, because setuid(2), called
* above, is supposed to set the real and effective
* uid as well as the saved set-user ID.
*
* However, the results are platform dependent,
* based on whether or not the euid at
* execution start was 0 or not. See
* https://is.gd/QVO35q for details.
*
* In practice, we observe that:
* - NetBSD sets the saved set-user-ID in setuid(2)
* even for non-root
* - OS X and Linux do NOT set the saved set-user-ID
* in setuid(2) IF the euid was non-zero
*/
if (seteuid(suid) != -1) {
#ifdef _POSIX_SAVED_IDS
if (euid == 0) {
fprintf(stderr, "seteuid(%d) should not have succeeded!\n", euid);
}
#endif
}
if (snprintf(buf, BUFSIZ, "After attempted seteuid(%d)", suid) < 0) {
fprintf(stderr, "Unable to snprintf: %s\n", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
printUids(buf);
printf("(We expect the following call to open(2) to fail if setuid was 0 initially.)\n");
if ((fd = open(argv[1], O_RDONLY)) == -1) {
fprintf(stderr, "Unable to open %s: %s\n",
argv[1], strerror(errno));
} else {
if (euid == 0) {
printf("Wait, what? This shouldn't have worked!\n");
}
(void)close(fd);
}
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,100 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* Variant of 'simple-ls' that illustrates the
* difference between stat(2) and lstat(2).
*
* Create a few files and symlink to different types
* of files to show.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char *
getType(const struct stat sb) {
if (S_ISREG(sb.st_mode))
return "regular file";
else if (S_ISDIR(sb.st_mode))
return "directory";
else if (S_ISCHR(sb.st_mode))
return "character special";
else if (S_ISBLK(sb.st_mode))
return "block special";
else if (S_ISFIFO(sb.st_mode))
return "FIFO";
else if (S_ISLNK(sb.st_mode))
return "symbolic link";
else if (S_ISSOCK(sb.st_mode))
return "socket";
else
return "unknown";
}
int
main(int argc, char **argv) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "usage: %s dir_name\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((dp = opendir(argv[1])) == NULL) {
fprintf(stderr, "can't open '%s'\n", argv[1]);
exit(EXIT_FAILURE);
}
if (chdir(argv[1]) == -1) {
fprintf(stderr, "can't chdir to '%s': %s\n", argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
while ((dirp = readdir(dp)) != NULL) {
struct stat sb;
char *statType;
printf("%s: ", dirp->d_name);
if (stat(dirp->d_name, &sb) == -1) {
fprintf(stderr, "Can't stat %s: %s\n", dirp->d_name,
strerror(errno));
statType = "unknown";
} else {
statType = getType(sb);
}
if (lstat(dirp->d_name, &sb) == -1) {
fprintf(stderr,"Can't lstat %s: %s\n", dirp->d_name,
strerror(errno));
continue;
} else if (S_ISLNK(sb.st_mode)) {
printf("symlink to ");
}
printf("%s\n", statType);
}
(void)closedir(dp);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,44 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This simple program displays the stat data relevant to file sizes. */
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv) {
struct stat sb;
if (argc != 2) {
fprintf(stderr, "usage: %s file\n", argv[0]);
exit(1);
}
if (lstat(argv[1], &sb) == -1) {
fprintf(stderr, "Can't stat %s: %s\n", argv[1],
strerror(errno));
exit(1);
}
printf("st_size : %d\n", (int)sb.st_size);
printf("st_blocks : %d\n", (int)sb.st_blocks);
printf("st_blksize: %d\n", (int)sb.st_blksize);
exit(0);
}

View File

@ -0,0 +1,56 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* simple-ls.c
* Extremely low-power ls clone.
* ./simple-ls .
*/
#include <sys/types.h>
#include <ufs/ufs/dir.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char **argv) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "usage: %s dir_name\n", argv[0]);
exit(1);
}
if ((dp = opendir(argv[1])) == NULL ) {
fprintf(stderr, "can't open '%s'\n", argv[1]);
exit(1);
}
while ((dirp = readdir(dp)) != NULL ) {
write(STDOUT_FILENO, dirp, sizeof(*dirp));
//printf("%s: %d %ld\n", dirp->d_name, dirp->d_reclen, UFS_DIRECTSIZ(dirp->d_namlen));
//printf("%ld\n", sizeof(*dirp));
//printf("%s: %d %ld\n", dirp->d_name, dirp->d_reclen, UFS_DIRECTSIZ(dirp->d_namlen));
}
closedir(dp);
return(0);
}

View File

@ -0,0 +1,114 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This still very simple ls clone illustrates the use of the stat(2)
* family of functions to print out some information about the files in
* the given directory.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char **argv) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "usage: %s dir_name\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((dp = opendir(argv[1])) == NULL ) {
fprintf(stderr, "can't open '%s': %s\n", argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
if (chdir(argv[1]) == -1) {
fprintf(stderr, "can't chdir to '%s': %s\n", argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
while ((dirp = readdir(dp)) != NULL ) {
struct stat sb;
if (stat(dirp->d_name, &sb) == -1) {
fprintf(stderr, "Can't stat %s: %s\n", dirp->d_name,
strerror(errno));
if (lstat(dirp->d_name, &sb) == -1) {
fprintf(stderr,"Can't stat %s: %s\n", dirp->d_name,
strerror(errno));
continue;
}
}
printf("%s: ", dirp->d_name);
if (S_ISREG(sb.st_mode))
printf("regular file");
else if (S_ISDIR(sb.st_mode))
printf("directory");
else if (S_ISCHR(sb.st_mode))
printf("character special");
else if (S_ISBLK(sb.st_mode))
printf("block special");
else if (S_ISFIFO(sb.st_mode))
printf("FIFO");
else if (S_ISLNK(sb.st_mode))
printf("symbolic link");
else if (S_ISSOCK(sb.st_mode))
printf("socket");
else
printf("unknown");
printf(" -- according to stat\n");
if (lstat(dirp->d_name, &sb) == -1) {
fprintf(stderr,"Can't stat %s: %s\n", dirp->d_name,
strerror(errno));
continue;
}
printf("%s: ", dirp->d_name);
if (S_ISREG(sb.st_mode))
printf("regular file");
else if (S_ISDIR(sb.st_mode))
printf("directory");
else if (S_ISCHR(sb.st_mode))
printf("character special");
else if (S_ISBLK(sb.st_mode))
printf("block special");
else if (S_ISFIFO(sb.st_mode))
printf("FIFO");
else if (S_ISLNK(sb.st_mode))
printf("symbolic link");
else if (S_ISSOCK(sb.st_mode))
printf("socket");
else
printf("unknown");
printf(" -- according to lstat\n\n");
}
closedir(dp);
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,14 @@
Maccess access.c /^main(int argc, char **argv) {$/
Mchmod chmod.c /^main() {$/
Mdirentsize direntsize.c /^main(int argc, char **argv) {$/
Msetuid setuid.c /^main(int argc, char **argv) {$/
Msimple-ls simple-ls.c /^main(int argc, char **argv) {$/
Msimple-ls-stat simple-ls-stat.c /^main(int argc, char **argv) {$/
Msize size.c /^main(int argc, char **argv) {$/
Msls sls.c /^main(int argc, char **argv) {$/
Mstill-simple-ls still-simple-ls.c /^main(int argc, char **argv) {$/
Mumask umask.c /^main() {$/
getType simple-ls-stat.c /^getType(const struct stat sb) {$/
myOpen umask.c /^myOpen(const char *path) {$/
myseteuid setuid.c /^myseteuid(int myeuid) {$/
printUids setuid.c /^printUids(const char *msg) {$/

View File

@ -0,0 +1,68 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This simple program illustrates the use of a umask.
*
* First, set your umask to 022 and 'touch file'; the mode will be 0644.
*
* Next, run this program and find file1 with the same mode, but execute
* permissions added, file2 with the explicitly requested 0777 mode, and
* finally file3 with mode 0711, since we explicitly turned off other
* permissions.
*
* Observe that each time the flags passed to open(2) are identical.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void
myOpen(const char *path) {
int fd;
if ((fd = open(path, O_CREAT | O_EXCL | O_WRONLY,
S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IWGRP | S_IXGRP |
S_IROTH | S_IWOTH | S_IXOTH)) == -1) {
fprintf(stderr, "Unable to create %s: %s\n",
path, strerror(errno));
exit(EXIT_FAILURE);
}
(void)close(fd);
}
int
main() {
/* current umask from your shell will apply to 'file1' */
myOpen("file1");
umask(0);
/* turning all bits off means we will allow
* all the bits specified in open(2) */
myOpen("file2");
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
/* turning group/other permissions off in the
* umask means they won't be set in open(2) */
myOpen("file3");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,49 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This program illustrates the uselessness of an external cd(1) command,
* as required by POSIX.1; note that many Unix versions don't bother
* implementing /usr/bin/cd anymore, but FreeBSD and Mac OS X, for
* example, still provide it via a generic shell builtin wrapper:
* http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/usr.bin/alias/generic.sh?rev=HEAD;content-type=text%2Fplain
*/
#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char **argv) {
char buf[MAXPATHLEN];
if (argc != 2) {
fprintf(stderr, "%s: need a directory!\n", argv[0]);
return(EXIT_FAILURE);
}
if (chdir(argv[1]) == -1) {
fprintf(stderr, "%s: unable to chdir to %s: %s\n", argv[0],
argv[1], strerror(errno));
return(EXIT_FAILURE);
}
printf("Ok, cwd is now: %s\n", getcwd(buf, MAXPATHLEN));
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,139 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* https://stevens.netmeister.org/631/
*/
/* This program illustrates the use of the various
* 'getpw*' functions. If given a username or a uid,
* it will attempt to print the information for the
* given user, otherwise, it will iterate over all
* entries and print them out in /etc/passwd format.
*
* ./a.out 0
* ./a.out root
* ./a.out
*
* Btw, what happens when you run this program as root?
*/
/* We pulled in some code from id(1):
*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct passwd *who(char *);
void printAllEntries(void);
void printOneStruct(const struct passwd *pw);
struct passwd *
who(char *u)
{
struct passwd *pw;
long id;
char *ep;
/* Translate user argument into a pw pointer.
* First, try to get it as specified. If that
* fails, try it as a number. */
if ((pw = getpwnam(u)) != NULL) {
return pw;
}
id = strtol(u, &ep, 10);
if (*u && !*ep && (pw = getpwuid(id))) {
return pw;
}
errx(EXIT_FAILURE, "%s: No such user", u);
/* NOTREACHED */
return NULL;
}
void
printAllEntries(void) {
struct passwd *pw;
errno = 0;
while ((pw = getpwent()) != NULL) {
printOneStruct(pw);
}
if (errno) {
fprintf(stderr, "%s: Unable to call getpwent(3): %s\n",
getprogname(), strerror(errno));
exit(EXIT_FAILURE);
}
/* We're exiting after this call, so the
* kernel would close the password database
* for us, but since we want to develop
* good coding habits, we're calling
* endpwent(3) here just like we'd call
* close(2) in other programs. */
endpwent();
}
void
printOneStruct(const struct passwd *pw) {
assert(pw);
printf("%s:%s:%d:%d:%s:%s:%s\n", pw->pw_name, pw->pw_passwd,
pw->pw_uid, pw->pw_gid,
pw->pw_gecos, pw->pw_dir,
pw->pw_shell);
}
int
main(int argc, char ** argv)
{
(void)setprogname(argv[0]);
if (argc > 2) {
fprintf(stderr, "Usage: %s [name|uid]\n", getprogname());
exit(EXIT_FAILURE);
}
if (argc == 2) {
printOneStruct(who(argv[1]));
} else {
printAllEntries();
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,149 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* https://stevens.netmeister.org/631/
*/
/* This program is a trivial version of the 'groups'
* command.
*/
/* We pulled in some code from id(1):
*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct passwd *who(char *);
struct passwd *
who(char *u)
{
struct passwd *pw;
long id;
char *ep;
/* Translate user argument into a pw pointer.
* First, try to get it as specified. If that
* fails, try it as a number. */
if ((pw = getpwnam(u)) != NULL) {
return pw;
}
id = strtol(u, &ep, 10);
if (*u && !*ep && (pw = getpwuid(id))) {
return pw;
}
errx(EXIT_FAILURE, "%s: No such user", u);
/* NOTREACHED */
return NULL;
}
int
main(int argc, char ** argv) {
gid_t *groups, *glist;
int cnt, maxgroups, ngroups;
struct passwd *pw;
struct group *gr;
(void)setprogname(argv[0]);
if (argc > 2) {
(void)fprintf(stderr, "Usage: %s [name|uid]\n", getprogname());
exit(EXIT_FAILURE);
}
pw = argv[1] ? who(argv[1]) : NULL;
if ((maxgroups = sysconf(_SC_NGROUPS_MAX)) < 0) {
err(EXIT_FAILURE, "unable to call sysconf");
/* NOTREACHED */
}
if ((groups = malloc((maxgroups + 1) * sizeof(gid_t))) == NULL) {
err(EXIT_FAILURE, "unable to malloc");
/* NOTREACHED */
}
glist = groups;
if (pw) {
ngroups = maxgroups;
if (getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups)
== -1) {
if ((glist = malloc(ngroups * sizeof(gid_t))) == NULL) {
err(EXIT_FAILURE, "unable to malloc");
/* NOTREACHED */
}
(void)getgrouplist(pw->pw_name, pw->pw_gid, glist,
&ngroups);
}
} else {
glist[0] = getgid();
if ((ngroups = getgroups(maxgroups, glist + 1) + 1) == 0) {
err(EXIT_FAILURE, "unable to getgroups");
/* NOTREACHED */
}
}
for (cnt = 0; cnt < ngroups; ++cnt) {
if (cnt && glist[cnt] == glist[0]) {
continue;
}
if ((gr = getgrgid(glist[cnt])) == NULL) {
(void)fprintf(stderr, "%s: unable to getgrgid(%u): %s\n",
getprogname(), glist[cnt], strerror(errno));
} else {
(void)printf("%s", gr->gr_name);
if (cnt < ngroups) {
(void)printf(" ");
}
}
}
if (cnt) {
(void)printf("\n");
}
if (glist != groups) {
(void)free(glist);
}
(void)free(groups);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,38 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* The world's most trivial 'ln -s', in a way. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s source target\n", argv[0]);
exit(EXIT_FAILURE);
}
if (symlink(argv[1], argv[2]) < 0) {
fprintf(stderr, "Unable to symlink '%s' to '%s': %s\n",
argv[2], argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,38 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* The world's most trivial 'mv', in a way. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s from to\n", argv[0]);
exit(EXIT_FAILURE);
}
if (rename(argv[1], argv[2]) < 0) {
fprintf(stderr, "Unable to rename '%s' to '%s': %s\n",
argv[1], argv[2], strerror(errno));
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,60 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* Students frequently think that the result of 'sizeof'
* is equivalent to that of strlen(3). Let's illustrate
* the differences. */
#include <errno.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
printf("int: %ld\n", sizeof(int));
char buf[BUFSIZ];
printf("Fixed buffer, size known at compile time: \"buf[%d]\"\n", BUFSIZ);
printf("strlen: %lu - sizeof: %lu\n\n", strlen(buf), sizeof buf);
char buf2[2] = { 'a' };
printf("Fixed-size, initialized buffer: \"buf[2] = { 'a' }\"\n");
printf("strlen: %lu - sizeof: %lu\n\n", strlen(buf2), sizeof buf2);
char *s = "abcde";
printf("A pointer: 'char *s = \"abcde\"'\n");
printf("strlen: %lu - sizeof: %lu\n\n", strlen(s), sizeof s);
char buf3[] = "abcde";
printf("Another initialized buffer, implicitly sized: 'buf3[] =\"abcde\"'\n");
printf("strlen: %lu - sizeof: %lu\n\n", strlen(buf3), sizeof buf3);
if ((s = malloc(BUFSIZ)) == NULL) {
fprintf(stderr, "Unable to allocate memory: %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
printf("A pointer to malloc(3)'d memory:\n");
printf("strlen: %lu - sizeof: %lu\n\n", strlen(s), sizeof s);
(void)strncat(s, "0123456789", BUFSIZ);
printf("After strncat(3)ing \"0123456789\" to 's':\n");
printf("strlen: %lu - sizeof: %lu\n\n", strlen(s), sizeof s);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,84 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* ISO 8601 format is "YYYY-MM-DDTHH:MM:SSZ" */
#define ISO8601_LENGTH 20 + 1 /* +1 for NULL */
int
main() {
time_t t;
struct timeval tv;
struct timespec ts;
struct tm *tm;
char buf[ISO8601_LENGTH];
if ((t = time(NULL)) < 0) {
err(EXIT_FAILURE, "unable to call time()");
/* NOTREACHED */
}
(void)printf("time(3) says: %ld\n", t);
if (gettimeofday(&tv, NULL) < 0) {
err(EXIT_FAILURE, "unable to gettimeofday()");
/* NOTREACHED */
}
(void)printf("gettimeofday(2) says: %ld.%d\n", tv.tv_sec, tv.tv_usec);
if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
err(EXIT_FAILURE, "unable to call clock_gettime(2)");
/* NOTREACHED */
}
(void)printf("clock_gettime(2) says: %ld.%ld\n\n", ts.tv_sec, ts.tv_nsec);
if ((tm = gmtime(&t)) == NULL) {
err(EXIT_FAILURE, "unable to call gmtime()");
/* NOTREACHED */
}
(void)printf("asctime(3) says: %s", asctime(tm));
if ((tm = localtime(&t)) == NULL) {
err(EXIT_FAILURE, "unable to call gmtime()");
/* NOTREACHED */
}
(void)printf("localtime is: %s", asctime(tm));
tm->tm_sec = 0;
tm->tm_min = 0;
tm->tm_hour = 0;
tm->tm_mday = 1;
tm->tm_mon = 0;
tm->tm_year = 70;
tm->tm_isdst = 0;
if ((t = mktime(tm)) < 0) {
err(EXIT_FAILURE, "unable to call mktime()");
/* NOTREACHED */
}
(void)printf("epoch date is: %s", ctime(&t));
if ((strftime(buf, ISO8601_LENGTH, "%Y-%m-%dT%H:%M:%SZ", tm)) == 0) {
err(EXIT_FAILURE, "strftime failed");
/* NOTREACHED */
}
(void)printf("ISO8601 formatted: %s\n", buf);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,126 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This simple program is used to illustrate that the OS does not free up
* the disk space used by a file immediately after a call to unlink(2),
* but only after the last process with an open handle has terminated.
*
* Run like this:
*
* $ cc -Wall wait-unlink.c
* $ ./a.out
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void
runDf() {
printf("\nAvailable space is now:\n");
if (system("df .") != 0) {
perror("unable to run df(1)");
exit(EXIT_FAILURE);
}
}
int
main() {
int fd;
/* "/tmp" is a memory file system on our
* reference platform, so let's use a separate
* temporary directory backed by a "normal"
* filesystem. */
if (chdir("/var/tmp") == -1) {
perror("unable to cd to /var/tmp");
exit(EXIT_FAILURE);
}
runDf();
/* Hit return to continue. */
(void)getchar();
printf("Creating a 500M file...\n");
if (system("dd if=/dev/zero of=foo bs=1024k count=500 >/dev/null") != 0) {
perror("unable to dd a new file");
exit(EXIT_FAILURE);
}
runDf();
(void)getchar();
printf("\nLinking 'bar' to 'foo'...\n\n");
if (link("foo", "bar") == -1) {
perror("unable to create a second hard link");
exit(EXIT_FAILURE);
}
if (system("ls -li foo bar") != 0) {
perror("unable to run ls(1)");
exit(EXIT_FAILURE);
}
runDf();
(void)getchar();
if ((fd = open("foo", O_RDWR)) < 0) {
perror("can't open file");
exit(EXIT_FAILURE);
}
printf("\nOpened 'foo' on fd#%d.\n", fd);
(void)getchar();
if (unlink("foo") < 0) {
perror("error unlinking");
exit(EXIT_FAILURE);
}
printf("\nOk, foo unlinked.\n");
printf("Disk space not free'd since 'bar' still exists...\n");
/* We expect system(3) to fail here, since 'foo' no longer exists. */
(void)system("ls -li foo bar");
runDf();
(void)getchar();
printf("\nOk, now unlinking 'bar'...\n");
if (unlink("bar") < 0) {
perror("error unlinking");
exit(EXIT_FAILURE);
}
printf("\nOk, bar unlinked.\n");
(void)getchar();
printf("Disk space not free'd since I still have fd#%d open...\n", fd);
printf("\nRunning 'ls -li foo bar':\n");
(void)system("ls -li foo bar");
runDf();
(void)getchar();
printf("Now closing fd#%d...\n", fd);
/* Closing the file descriptor after having
* unlinked all references to the 500M file
* finally frees the disk space. */
(void)close(fd);
printf("\n...and done. Disk space is freed now.\n");
runDf();
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,58 @@
TARGET = slides
LATEX = latex
DVIPS = dvips -o
PS2PDF = ps2pdf
PDFTOTEXT= pdftotext
FIGURES= pics/terminal.eps \
pics/ide.eps \
pics/compiler.eps \
pics/ls.eps \
pics/ls-changed1.eps \
pics/ls-changed2.eps \
pics/ls-changed3.eps \
pics/ls-changed4.eps \
pics/compiler_monster.eps \
pics/makerbot.eps \
pics/debugging.eps \
pics/vim.eps
.SUFFIXES: .tex .dvi .ps .pdf .fig .eps .png .dot .jpg .gif
all: $(FIGURES) $(TARGET).dvi
slides:
.tex.dvi:
$(LATEX) $<
$(LATEX) $<
.jpg.eps:
convert $< $@
.gif.eps:
convert $< $@
.png.eps:
pngtopnm $< | pnmtops > $@
.dot.eps:
dot -Tpng $< | pngtopnm | pnmtops > $@
.fig.eps:
fig2dev -L eps $< > $@
ps: $(TARGET).dvi $(TARGET).ps
.dvi.ps:
$(DVIPS) $@ $<
pdf: $(FIGURES) $(TARGET).dvi $(TARGET).ps $(TARGET).pdf
.ps.pdf:
$(PS2PDF) $< $@
clean:
rm -f **.bbl *.blg *.log *.aux *.dvi *.ps *.pdf *.toc *.bak *.lof ${FIGURES} *.out
rm -fr $(TARGET)/

View File

@ -0,0 +1,30 @@
all: a.out
cpp: preprocess
preprocess: hello.i
hello.i: hello.c
cpp -P $> >$@
compile: hello.s
hello.s: hello.i
cc -S $> -o $@
assemble: hello.o
hello.o: hello.s
as -o $@ $<
link: a.out
a.out: hello.o
ld -dynamic-linker /usr/libexec/ld.elf_so /usr/lib/crt0.o \
/usr/lib/crti.o /usr/lib/crtbegin.o hello.o \
-lc /usr/lib/crtend.o /usr/lib/crtn.o
clean:
rm -f hello.i hello.o hello.s a.out

Binary file not shown.

View File

@ -0,0 +1,54 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* A very simple program to illustrate the different stages in the
* compilation process. First, use cpp(1) to pre-process the file; repeat
* with FOOD defined to a different value. Compare output, illustrate
* that code is pulled in by the preprocessor and macros expanded. Then,
* compile hello.i to hello.s and show the resulting assembly output
* before using as(1) to generate object code. Use objdump(1) (or
* similar) to disassemble the object code. Finally, use ld(1) to create
* an executable.
*
* To illustrate compiler optimization, compile with
* '-O0 -S' and once with '-O4 -S' and compare the
* output. You should notice that the calls to func1
* and func2 are eliminated when optimization is
* turned on.
*
* The file 'dump' includes the traced output of the compiler invocation.
* Show the different stages again.
*/
#include <stdio.h>
#ifndef FOOD
#define FOOD "Avocado"
#endif
void
func2(void) {
printf("%s: great on anything.\n", FOOD);
}
void
func1(void) {
func2();
}
int
main() {
func1();
return 0;
}

View File

@ -0,0 +1,342 @@
static __inline long long __zeroll(void) { return 0; }
static __inline unsigned long long __zeroull(void) { return 0; }
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef short int __int16_t;
typedef short unsigned int __uint16_t;
typedef int __int32_t;
typedef unsigned int __uint32_t;
typedef long int __int64_t;
typedef long unsigned int __uint64_t;
typedef long int __intptr_t;
typedef long unsigned int __uintptr_t;
typedef char * __caddr_t;
typedef __uint32_t __gid_t;
typedef __uint32_t __in_addr_t;
typedef __uint16_t __in_port_t;
typedef __uint32_t __mode_t;
typedef __int64_t __off_t;
typedef __int32_t __pid_t;
typedef __uint8_t __sa_family_t;
typedef unsigned int __socklen_t;
typedef __uint32_t __uid_t;
typedef __uint64_t __fsblkcnt_t;
typedef __uint64_t __fsfilcnt_t;
struct __tag_wctrans_t;
typedef struct __tag_wctrans_t *__wctrans_t;
struct __tag_wctype_t;
typedef struct __tag_wctype_t *__wctype_t;
typedef union {
__int64_t __mbstateL;
char __mbstate8[128];
} __mbstate_t;
typedef __builtin_va_list __va_list;
typedef long unsigned int size_t;
typedef long int ssize_t;
typedef struct __sfpos {
__off_t _pos;
__mbstate_t _mbstate_in, _mbstate_out;
} fpos_t;
struct __sbuf {
unsigned char *_base;
int _size;
};
typedef struct __sFILE {
unsigned char *_p;
int _r;
int _w;
unsigned short _flags;
short _file;
struct __sbuf _bf;
int _lbfsize;
void *_cookie;
int (*_close)(void *);
ssize_t (*_read) (void *, void *, size_t);
__off_t (*_seek) (void *, __off_t, int);
ssize_t (*_write)(void *, const void *, size_t);
struct __sbuf _ext;
unsigned char *_up;
int _ur;
unsigned char _ubuf[3];
unsigned char _nbuf[1];
int (*_flush)(void *);
char _lb_unused[sizeof(struct __sbuf) - sizeof(int (*)(void *))];
int _blksize;
__off_t _offset;
} FILE;
#pragma GCC visibility push(default)
extern FILE __sF[3];
#pragma GCC visibility pop
#pragma GCC visibility push(default)
void clearerr(FILE *);
int fclose(FILE *);
int feof(FILE *);
int ferror(FILE *);
int fflush(FILE *);
int fgetc(FILE *);
char *fgets(char * restrict, int, FILE * restrict);
FILE *fopen(const char * restrict , const char * restrict);
int fprintf(FILE * restrict, const char * restrict, ...)
__attribute__((__format__ (__printf__, 2, 3)));
int fputc(int, FILE *);
int fputs(const char * restrict, FILE * restrict);
size_t fread(void * restrict, size_t, size_t, FILE * restrict);
FILE *freopen(const char * restrict, const char * restrict,
FILE * restrict);
int fscanf(FILE * restrict, const char * restrict, ...)
__attribute__((__format__ (__scanf__, 2, 3)));
int fseek(FILE *, long, int);
long ftell(FILE *);
size_t fwrite(const void * restrict, size_t, size_t, FILE * restrict);
int getc(FILE *);
int getchar(void);
void perror(const char *);
int printf(const char * restrict, ...)
__attribute__((__format__ (__printf__, 1, 2)));
int putc(int, FILE *);
int putchar(int);
int puts(const char *);
int remove(const char *);
void rewind(FILE *);
int scanf(const char * restrict, ...)
__attribute__((__format__ (__scanf__, 1, 2)));
void setbuf(FILE * restrict, char * restrict);
int setvbuf(FILE * restrict, char * restrict, int, size_t);
int sscanf(const char * restrict, const char * restrict, ...)
__attribute__((__format__ (__scanf__, 2, 3)));
FILE *tmpfile(void);
int ungetc(int, FILE *);
int vfprintf(FILE * restrict, const char * restrict, __va_list)
__attribute__((__format__ (__printf__, 2, 0)));
int vprintf(const char * restrict, __va_list)
__attribute__((__format__ (__printf__, 1, 0)));
char *gets(char *);
int sprintf(char * restrict, const char * restrict, ...)
__attribute__((__format__ (__printf__, 2, 3)));
char *tmpnam(char *);
int vsprintf(char * restrict, const char * restrict,
__va_list)
__attribute__((__format__ (__printf__, 2, 0)));
int rename (const char *, const char *);
#pragma GCC visibility pop
int fgetpos(FILE * restrict, fpos_t * restrict) __asm("__fgetpos50");
int fsetpos(FILE *, const fpos_t *) __asm("__fsetpos50");
#pragma GCC visibility push(default)
char *ctermid(char *);
char *cuserid(char *);
FILE *fdopen(int, const char *);
int fileno(FILE *);
#pragma GCC visibility pop
#pragma GCC visibility push(default)
void flockfile(FILE *);
int ftrylockfile(FILE *);
void funlockfile(FILE *);
int getc_unlocked(FILE *);
int getchar_unlocked(void);
int putc_unlocked(int, FILE *);
int putchar_unlocked(int);
#pragma GCC visibility pop
#pragma GCC visibility push(default)
int pclose(FILE *);
FILE *popen(const char *, const char *);
#pragma GCC visibility pop
#pragma GCC visibility push(default)
FILE *popenve(const char *, char *const *, char *const *, const char *);
#pragma GCC visibility pop
#pragma GCC visibility push(default)
int snprintf(char * restrict, size_t, const char * restrict, ...)
__attribute__((__format__ (__printf__, 3, 4)));
int vsnprintf(char * restrict, size_t, const char * restrict,
__va_list)
__attribute__((__format__ (__printf__, 3, 0)));
#pragma GCC visibility pop
#pragma GCC visibility push(default)
int getw(FILE *);
int putw(int, FILE *);
char *tempnam(const char *, const char *);
#pragma GCC visibility pop
typedef __off_t off_t;
#pragma GCC visibility push(default)
int fseeko(FILE *, __off_t, int);
__off_t ftello(FILE *);
#pragma GCC visibility pop
#pragma GCC visibility push(default)
int vscanf(const char * restrict, __va_list)
__attribute__((__format__ (__scanf__, 1, 0)));
int vfscanf(FILE * restrict, const char * restrict, __va_list)
__attribute__((__format__ (__scanf__, 2, 0)));
int vsscanf(const char * restrict, const char * restrict,
__va_list)
__attribute__((__format__ (__scanf__, 2, 0)));
#pragma GCC visibility pop
#pragma GCC visibility push(default)
int asprintf(char ** restrict, const char * restrict, ...)
__attribute__((__format__ (__printf__, 2, 3)));
char *fgetln(FILE * restrict, size_t * restrict);
char *fparseln(FILE *, size_t *, size_t *, const char[3], int);
int fpurge(FILE *);
void setbuffer(FILE *, char *, int);
int setlinebuf(FILE *);
int vasprintf(char ** restrict, const char * restrict,
__va_list)
__attribute__((__format__ (__printf__, 2, 0)));
const char *fmtcheck(const char *, const char *)
__attribute__((__format_arg__ (2)));
#pragma GCC visibility pop
#pragma GCC visibility push(default)
FILE *funopen(const void *,
int (*)(void *, char *, int),
int (*)(void *, const char *, int),
__off_t (*)(void *, __off_t, int),
int (*)(void *));
FILE *funopen2(const void *,
ssize_t (*)(void *, void *, size_t),
ssize_t (*)(void *, const void *, size_t),
__off_t (*)(void *, __off_t, int),
int (*)(void *),
int (*)(void *));
#pragma GCC visibility pop
#pragma GCC visibility push(default)
int __srget(FILE *);
int __swbuf(int, FILE *);
#pragma GCC visibility pop
static __inline int __sputc(int _c, FILE *_p) {
if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
return *_p->_p++ = (unsigned char)_c;
else
return __swbuf(_c, _p);
}
#pragma GCC visibility push(default)
int vdprintf(int, const char * restrict, __va_list)
__attribute__((__format__ (__printf__, 2, 0)));
int dprintf(int, const char * restrict, ...)
__attribute__((__format__ (__printf__, 2, 3)));
#pragma GCC visibility pop
#pragma GCC visibility push(default)
FILE *fmemopen(void * restrict, size_t, const char * restrict);
FILE *open_memstream(char **, size_t *);
ssize_t getdelim(char ** restrict, size_t * restrict, int,
FILE * restrict);
ssize_t getline(char ** restrict, size_t * restrict, FILE * restrict);
#pragma GCC visibility pop
typedef struct _locale *locale_t;
#pragma GCC visibility push(default)
int fprintf_l(FILE * restrict, locale_t, const char * restrict, ...)
__attribute__((__format__ (__printf__, 3, 4)));
int vfprintf_l(FILE * restrict, locale_t, const char * restrict,
__va_list) __attribute__((__format__ (__printf__, 3, 0)));
int printf_l(locale_t, const char * restrict, ...)
__attribute__((__format__ (__printf__, 2, 3)));
int vprintf_l(locale_t, const char * restrict, __va_list)
__attribute__((__format__ (__printf__, 2, 0)));
int asprintf_l(char ** restrict, locale_t, const char * restrict, ...)
__attribute__((__format__ (__printf__, 3, 4)));
int vasprintf_l(char ** restrict, locale_t, const char * restrict,
__va_list)
__attribute__((__format__ (__printf__, 3, 0)));
int vdprintf_l(int, locale_t, const char * restrict, __va_list)
__attribute__((__format__ (__printf__, 3, 0)));
int dprintf_l(int, locale_t, const char * restrict, ...)
__attribute__((__format__ (__printf__, 3, 4)));
int snprintf_l(char * restrict, size_t, locale_t,
const char * restrict, ...) __attribute__((__format__ (__printf__, 4, 5)));
int vsnprintf_l(char * restrict, size_t, locale_t,
const char * restrict, __va_list) __attribute__((__format__ (__printf__, 4, 0)));
int sprintf_l(char * restrict, locale_t, const char * restrict, ...)
__attribute__((__format__ (__printf__, 3, 4)));
int vsprintf_l(char * restrict, locale_t, const char * restrict,
__va_list) __attribute__((__format__ (__printf__, 3, 0)));
int fscanf_l(FILE * restrict, locale_t, const char * restrict, ...)
__attribute__((__format__ (__scanf__, 3, 4)));
int scanf_l(locale_t, const char * restrict, ...)
__attribute__((__format__ (__scanf__, 2, 3)));
int sscanf_l(const char * restrict, locale_t,
const char * restrict, ...) __attribute__((__format__ (__scanf__, 3, 4)));
int vscanf_l(locale_t, const char * restrict, __va_list)
__attribute__((__format__ (__scanf__, 2, 0)));
int vfscanf_l(FILE * restrict, locale_t, const char * restrict,
__va_list) __attribute__((__format__ (__scanf__, 3, 0)));
int vsscanf_l(const char * restrict, locale_t, const char * restrict,
__va_list) __attribute__((__format__ (__scanf__, 3, 0)));
int snprintf_ss(char *restrict, size_t, const char * restrict, ...)
__attribute__((__format__ (__printf__, 3, 4)));
int vsnprintf_ss(char *restrict, size_t, const char * restrict, __va_list)
__attribute__((__format__ (__printf__, 3, 0)));
#pragma GCC visibility pop
void
func2(void) {
printf("%s: great on anything.\n", "avocado");
}
void
func1(void) {
func2();
}
int
main() {
func1();
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,66 @@
.file "hello.i"
.text
.section .rodata
.LC0:
.string "avocado"
.LC1:
.string "%s: great on anything.\n"
.text
.globl func2
.type func2, @function
func2:
.LFB3:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE3:
.size func2, .-func2
.globl func1
.type func1, @function
func1:
.LFB4:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
call func2
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE4:
.size func1, .-func1
.globl main
.type main, @function
main:
.LFB5:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
call func1
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE5:
.size main, .-main
.ident "GCC: (nb4 20200810) 7.5.0"

View File

@ -0,0 +1,45 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This file is used together with the file 'main.c' to
* help students use gdb(1) to understand
* manipulations of strings and buffers.
*
* See https://youtu.be/hgcj7iAxhhU as well as
* 'pointer.c'
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define DATA2 "Hello, I'm buf2!"
#define DATA3 "Hello, I'm buf3!"
void
printBufs(long n) {
char *buf = malloc(n);
char *buf2 = malloc(8);
char *buf3 = malloc(8);
strcpy(buf2, DATA2);
strcpy(buf3, DATA3);
gets(buf);
printf("buf is : '%s'\n", buf);
printf("buf2 is: '%s'\n", buf2);
printf("buf3 is: '%s'\n", buf3);
}

View File

@ -0,0 +1,49 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This file is used to illustrate how to step through
* a program at execution time using gdb(1).
*
* To this end, it contains a number of mistakes.
*
* See https://youtu.be/fOp4Q4mnTD4 for how to fix
* them.
*/
/* The Fibonacci sequence is defined such that each number
* is the sum of the two preceding ones. */
#include <stdio.h>
#include <stdlib.h>
int
fib(int i) {
if (i == 0) {
return 0;
} else {
return fib(i-2) + fib(i-1);
}
}
int
main(int argc, char **argv) {
if (argc != 2) {
printf("usage: %s num\n", argv[0]);
exit(EXIT_FAILURE);
}
printf("%d\n", fib(atoi(argv[1])));
exit(EXIT_SUCCESS);
}

View File

@ -0,0 +1,36 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This file is used together with the file 'buf.c' to
* help students use gdb(1) to understand
* manipulations of strings and buffers.
*
* See https://youtu.be/hgcj7iAxhhU as well as
* 'pointer.c'
*/
#include <stdlib.h>
#include <stdio.h>
void printBufs(long);
int
main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s num\n", argv[0]);
exit(EXIT_FAILURE);
}
printBufs(strtol(argv[1], NULL, 10));
}

View File

@ -0,0 +1,56 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This program is all sorts of terrible. If I catch
* you doing anything like this in your code, you'll
* have a hard time getting any points.
*
* We use this code to illustrate how "strings" work,
* as well as how to inspect arrays and pointers using
* gdb(1).
*
* Compile this with '-g'. Run it as './a.out foo',
* then run it in the debugger, break in 'main', and
* inspect the different pointers at each step to
* better understand what is going on.
*/
#include <stdio.h>
#include <string.h>
int
main(int argc, char **argv) {
char *p = argv[0];
char *q = argv[1];
(void)argc;
strcat(argv[0], "/");
strcat(p, argv[1]);
printf("argv[0]: %s\n", argv[0]);
printf("argv[1]: %s\n\n", argv[1]);
*(p + 1) = '\0';
q[0] = 'm';
printf("argv[0]: %s\n", argv[0]);
printf("argv[0]: %s\n", argv[0]);
p[1] = '/';
printf("argv[0]: %s\n", argv[0]);
return 0;
}

View File

@ -0,0 +1,73 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* simple-ls.c
* Extremely low-power ls clone.
* ./simple-ls .
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void
printOwner(char *name, struct stat sb) {
struct passwd *pwd;
pwd = getpwuid(sb.st_uid);
printf("%s (%s)\n", name, pwd->pw_name);
}
int
main(int argc, char **argv) {
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "usage: %s dir_name\n", argv[0]);
exit(1);
}
if ((dp = opendir(argv[1])) == NULL) {
fprintf(stderr, "can't open '%s'\n", argv[1]);
exit(1);
}
if (chdir(argv[1]) == -1) {
fprintf(stderr, "can't chdir to '%s': %s\n", argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
while ((dirp = readdir(dp)) != NULL) {
struct stat sb;
if (stat(dirp->d_name, &sb) == -1) {
fprintf(stderr, "Can't stat %s: %s\n", dirp->d_name,
strerror(errno));
continue;
}
printOwner(dirp->d_name, sb);
}
closedir(dp);
return(0);
}

View File

@ -0,0 +1,21 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
int
main() {
printf("Welcome to CS631 Advanced Programming in the UNIX Environment, %s!\n", getlogin());
}

Binary file not shown.

View File

@ -0,0 +1,28 @@
# A slightly better Makefile. As the first one, but much shorter, since
# we're using the various built-in rules and definitions in make(1).
#
# also see "cpp -M" and "cpp -MM"
PROG= ls
OBJS= cmp.o ls.o main.o print.o stat_flags.o util.o
# If commented out, defaults will be used. If uncommented, these values
# will be used, even though there is no other explicit mention of this
# variable in this Makefile.
#CFLAGS= -Wall -g
all: ${PROG}
showvars:
@echo "CC=${CC}"
@echo "CFLAGS=${CFLAGS}"
@echo "LDFLAGS=${LDFLAGS}"
@echo "PROG=${PROG}"
@echo "OBJS=${OBJS}"
${PROG}: ${OBJS}
@echo $@ depends on $?
${CC} ${LDFLAGS} ${OBJS} -o ${PROG}
clean:
rm -f ls *.o

View File

@ -0,0 +1,36 @@
# A simplistic Makefile used to illustrate the very basics of make(1).
# The following Makefiles build on this and show more realistic usage.
#
# Run 'make', then 'touch ls.h' and 'make' again.
CC=cc
all: ls
showvars:
@echo "CC=${CC}"
@echo "CFLAGS=${CFLAGS}"
ls: cmp.o ls.o main.o print.o stat_flags.o util.o
${CC} cmp.o ls.o main.o print.o stat_flags.o util.o -o ls
cmp.o: extern.h ls.h
${CC} -c cmp.c
ls.o: extern.h ls.h
${CC} -c ls.c
main.o: extern.h ls.h
${CC} -c main.c
print.o: extern.h ls.h
${CC} -c print.c
stat_flags.o: stat_flags.h
${CC} -c stat_flags.c
util.o: extern.h ls.h
${CC} -c util.c
clean:
rm -f ls *.o

View File

@ -0,0 +1,19 @@
# A slightly better Makefile. As the first one, but much shorter, since
# we're using the various built-in rules and definitions in make(1).
PROG= ls
OBJS= cmp.o ls.o main.o print.o stat_flags.o util.o
# If commented out, defaults will be used. If uncommented, these values
# will be used, even though there is no other explicit mention of this
# variable in this Makefile.
#CFLAGS= -Wall -g
all: ${PROG}
${PROG}: ${OBJS}
@echo $@ depends on $?
${CC} ${LDFLAGS} ${OBJS} -o ${PROG}
clean:
rm -f ls *.o

View File

@ -0,0 +1,29 @@
# Like the previous Makefiles, only introducing suffixes. Repeats the
# lesson that Unix doesn't care what things are named.
PROG= ls
OBJS= cmp.o ls.b main.b print.b stat_flags.bar util.bar
CFLAGS= -Wall -g
.SUFFIXES: .c .b .bar
all: ${PROG}
showvars:
@echo "CC=${CC}"
@echo "CFLAGS=${CFLAGS}"
@echo "LDFLAGS=${LDFLAGS}"
@echo "PROG=${PROG}"
@echo "OBJS=${OBJS}"
${PROG}: ${OBJS}
@echo $@ depends on $?
${CC} ${LDFLAGS} ${OBJS} -o ${PROG}
.c.b:
${CC} -c $< -o $@
.c.bar:
${CC} ${CFLAGS} -c $< -o $@
clean:
rm -f ${PROG} ${OBJS}

View File

@ -0,0 +1,26 @@
# Almost identical to 'Makefile.2' - use diff to find out what's
# different. Then use both Makefile.2 and Makefile.4 to illustrate
# precedence of variables.
PROG= ls
OBJS= cmp.o ls.o main.o print.o stat_flags.o util.o
# If commented out, defaults will be used. If uncommented, these values
# will be used, even though there is no other explicit mention of this
# variable in this Makefile.
CFLAGS= -Wall -g
all: ${PROG}
showvars:
@echo "CC=${CC}"
@echo "CFLAGS=${CFLAGS}"
@echo "LDFLAGS=${LDFLAGS}"
@echo "PROG=${PROG}"
@echo "OBJS=${OBJS}"
${PROG}: ${OBJS}
@echo $@ depends on $?
${CC} ${LDFLAGS} ${OBJS} -o ${PROG}
clean:
rm -f ls *.o

View File

@ -0,0 +1,19 @@
# A slightly better Makefile. Let's define a "suffix rule" to
# create object files from source files.
# Let's also introduce the concept of variables.
PROG= ls
OBJS= cmp.o ls.o main.o print.o stat_flags.o util.o
CFLAGS= -Wall -g
all: ${PROG}
depend:
mkdep -- ${CFLAGS} *.c
${PROG}: ${OBJS}
@echo $@ depends on $?
${CC} ${OBJS} -o ${PROG} ${LDFLAGS}
clean:
rm -f ${PROG} ${OBJS}

View File

@ -0,0 +1,2 @@
all:
cc ${CFLAGS} *.c

Binary file not shown.

View File

@ -0,0 +1,209 @@
/* $NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cmp.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>
#include <string.h>
#include "ls.h"
#include "extern.h"
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \
defined(_XOPEN_SOURCE) || defined(__NetBSD__)
#define ATIMENSEC_CMP(x, op, y) ((x)->st_atimensec op (y)->st_atimensec)
#define CTIMENSEC_CMP(x, op, y) ((x)->st_ctimensec op (y)->st_ctimensec)
#define MTIMENSEC_CMP(x, op, y) ((x)->st_mtimensec op (y)->st_mtimensec)
#else
#define ATIMENSEC_CMP(x, op, y) \
((x)->st_atimespec.tv_nsec op (y)->st_atimespec.tv_nsec)
#define CTIMENSEC_CMP(x, op, y) \
((x)->st_ctimespec.tv_nsec op (y)->st_ctimespec.tv_nsec)
#define MTIMENSEC_CMP(x, op, y) \
((x)->st_mtimespec.tv_nsec op (y)->st_mtimespec.tv_nsec)
#endif
int
namecmp(const FTSENT *a, const FTSENT *b)
{
return (strcmp(a->fts_name, b->fts_name));
}
int
revnamecmp(const FTSENT *a, const FTSENT *b)
{
return (strcmp(b->fts_name, a->fts_name));
}
int
modcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
return (1);
else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
return (-1);
else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (1);
else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (-1);
else
return (namecmp(a, b));
}
int
revmodcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
return (-1);
else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
return (1);
else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (-1);
else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (1);
else
return (revnamecmp(a, b));
}
int
acccmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_atime > a->fts_statp->st_atime)
return (1);
else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
return (-1);
else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (1);
else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (-1);
else
return (namecmp(a, b));
}
int
revacccmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_atime > a->fts_statp->st_atime)
return (-1);
else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
return (1);
else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (-1);
else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (1);
else
return (revnamecmp(a, b));
}
int
statcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
return (1);
else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
return (-1);
else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (1);
else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (-1);
else
return (namecmp(a, b));
}
int
revstatcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
return (-1);
else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
return (1);
else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (-1);
else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (1);
else
return (revnamecmp(a, b));
}
int
sizecmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_size > a->fts_statp->st_size)
return (1);
if (b->fts_statp->st_size < a->fts_statp->st_size)
return (-1);
else
return (namecmp(a, b));
}
int
revsizecmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_size > a->fts_statp->st_size)
return (-1);
if (b->fts_statp->st_size < a->fts_statp->st_size)
return (1);
else
return (revnamecmp(a, b));
}
#if 0
int
sillysort(const FTSENT *a, const FTSENT *b)
{
(void)a; (void)b;
int n[3] = { -1, 0, 1 };
return n[((long)&n)%3];
}
#endif

View File

@ -0,0 +1,53 @@
/* $NetBSD: extern.h,v 1.17 2011/08/29 14:44:21 joerg Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
*/
int acccmp(const FTSENT *, const FTSENT *);
int revacccmp(const FTSENT *, const FTSENT *);
int modcmp(const FTSENT *, const FTSENT *);
int revmodcmp(const FTSENT *, const FTSENT *);
int namecmp(const FTSENT *, const FTSENT *);
int revnamecmp(const FTSENT *, const FTSENT *);
int statcmp(const FTSENT *, const FTSENT *);
int revstatcmp(const FTSENT *, const FTSENT *);
int sizecmp(const FTSENT *, const FTSENT *);
int revsizecmp(const FTSENT *, const FTSENT *);
int ls_main(int, char *[]);
int printescaped(const char *);
void printacol(DISPLAY *);
void printcol(DISPLAY *);
void printlong(DISPLAY *);
void printscol(DISPLAY *);
void printstream(DISPLAY *);
int safe_print(const char *);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,81 @@
/* $NetBSD: ls.h,v 1.19 2014/02/20 18:56:36 christos Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ls.h 8.1 (Berkeley) 5/31/93
*/
#define NO_PRINT 1
extern long blocksize; /* block size units */
extern int f_accesstime; /* use time of last access */
extern int f_flags; /* show flags associated with a file */
extern int f_grouponly; /* long listing without owner */
extern int f_humanize; /* humanize size field */
extern int f_commas; /* separate size field with commas */
extern int f_inode; /* print inode */
extern int f_longform; /* long listing format */
extern int f_octal; /* print octal escapes for nongraphic characters */
extern int f_octal_escape; /* like f_octal but use C escapes if possible */
extern int f_sectime; /* print the real time for all files */
extern int f_size; /* list size in short listing */
extern int f_statustime; /* use time of last mode change */
extern int f_type; /* add type character for non-regular files */
extern int f_typedir; /* add type character for directories */
extern int f_nonprint; /* show unprintables as ? */
extern int f_fullpath; /* print full pathname, not filename */
extern int f_leafonly; /* when recursing, print leaf names only */
typedef struct {
FTSENT *list;
u_int64_t btotal;
u_int64_t stotal;
int entries;
unsigned int maxlen;
int s_block;
int s_flags;
int s_group;
int s_inode;
int s_nlink;
int s_size;
int s_user;
int s_major;
int s_minor;
} DISPLAY;
typedef struct {
char *user;
char *group;
char *flags;
char data[1];
} NAMES;

View File

@ -0,0 +1,51 @@
/* $NetBSD: main.c,v 1.5 2016/09/05 01:00:07 sevan Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: main.c,v 1.5 2016/09/05 01:00:07 sevan Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <fts.h>
#include "ls.h"
#include "extern.h"
#include "stat_flags.h"
int
main(int argc, char *argv[])
{
return ls_main(argc, argv);
/* NOTREACHED */
}

View File

@ -0,0 +1,497 @@
/* $NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
#else
__RCSID("$NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <inttypes.h>
#include <fts.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <tzfile.h>
#include <unistd.h>
#include <util.h>
#include "ls.h"
#include "extern.h"
extern int termwidth;
static int printaname(FTSENT *, int, int);
static void printlink(FTSENT *);
static void printtime(time_t);
static void printtotal(DISPLAY *dp);
static int printtype(u_int);
static time_t now;
#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
static int
safe_printpath(const FTSENT *p) {
int chcnt;
if (f_fullpath) {
chcnt = safe_print(p->fts_path);
chcnt += safe_print("/");
} else
chcnt = 0;
return chcnt + safe_print(p->fts_name);
}
static int
printescapedpath(const FTSENT *p) {
int chcnt;
if (f_fullpath) {
chcnt = printescaped(p->fts_path);
chcnt += printescaped("/");
} else
chcnt = 0;
return chcnt + printescaped(p->fts_name);
}
static int
printpath(const FTSENT *p) {
if (f_fullpath)
return printf("%s/%s", p->fts_path, p->fts_name);
else
return printf("%s", p->fts_name);
}
void
printscol(DISPLAY *dp)
{
FTSENT *p;
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
(void)printaname(p, dp->s_inode, dp->s_block);
(void)putchar('\n');
}
}
void
printlong(DISPLAY *dp)
{
struct stat *sp;
FTSENT *p;
NAMES *np;
char buf[20], szbuf[5];
now = time(NULL);
if (!f_leafonly)
printtotal(dp); /* "total: %u\n" */
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
sp = p->fts_statp;
if (f_inode)
(void)printf("%*"PRIu64" ", dp->s_inode, sp->st_ino);
if (f_size) {
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf),
sp->st_blocks * S_BLKSIZE,
"", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
(void)printf("%*s ", dp->s_block, szbuf);
} else {
(void)printf(f_commas ? "%'*llu " : "%*llu ",
dp->s_block,
(unsigned long long)howmany(sp->st_blocks,
blocksize));
}
}
(void)strmode(sp->st_mode, buf);
np = p->fts_pointer;
(void)printf("%s %*lu ", buf, dp->s_nlink,
(unsigned long)sp->st_nlink);
if (!f_grouponly)
(void)printf("%-*s ", dp->s_user, np->user);
(void)printf("%-*s ", dp->s_group, np->group);
if (f_flags)
(void)printf("%-*s ", dp->s_flags, np->flags);
if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
(void)printf("%*lld, %*lld ",
dp->s_major, (long long)major(sp->st_rdev),
dp->s_minor, (long long)minor(sp->st_rdev));
else
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf),
sp->st_size, "", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
(void)printf("%*s ", dp->s_size, szbuf);
} else {
(void)printf(f_commas ? "%'*llu " : "%*llu ",
dp->s_size, (unsigned long long)
sp->st_size);
}
if (f_accesstime)
printtime(sp->st_atime);
else if (f_statustime)
printtime(sp->st_ctime);
else
printtime(sp->st_mtime);
if (f_octal || f_octal_escape)
(void)safe_printpath(p);
else if (f_nonprint)
(void)printescapedpath(p);
else
(void)printpath(p);
if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
(void)printtype(sp->st_mode);
if (S_ISLNK(sp->st_mode))
printlink(p);
(void)putchar('\n');
}
}
void
printcol(DISPLAY *dp)
{
static FTSENT **array;
static int lastentries = -1;
FTSENT *p;
int base, chcnt, col, colwidth, num;
int numcols, numrows, row;
colwidth = dp->maxlen;
if (f_inode)
colwidth += dp->s_inode + 1;
if (f_size) {
if (f_humanize)
colwidth += dp->s_size + 1;
else
colwidth += dp->s_block + 1;
}
if (f_type || f_typedir)
colwidth += 1;
colwidth += 1;
if (termwidth < 2 * colwidth) {
printscol(dp);
return;
}
/*
* Have to do random access in the linked list -- build a table
* of pointers.
*/
if (dp->entries > lastentries) {
FTSENT **newarray;
newarray = realloc(array, dp->entries * sizeof(FTSENT *));
if (newarray == NULL) {
warn(NULL);
printscol(dp);
return;
}
lastentries = dp->entries;
array = newarray;
}
for (p = dp->list, num = 0; p; p = p->fts_link)
if (p->fts_number != NO_PRINT)
array[num++] = p;
numcols = termwidth / colwidth;
colwidth = termwidth / numcols; /* spread out if possible */
numrows = num / numcols;
if (num % numcols)
++numrows;
printtotal(dp); /* "total: %u\n" */
for (row = 0; row < numrows; ++row) {
for (base = row, chcnt = col = 0; col < numcols; ++col) {
chcnt = printaname(array[base], dp->s_inode,
f_humanize ? dp->s_size : dp->s_block);
if ((base += numrows) >= num)
break;
while (chcnt++ < colwidth)
(void)putchar(' ');
}
(void)putchar('\n');
}
}
void
printacol(DISPLAY *dp)
{
FTSENT *p;
int chcnt, col, colwidth;
int numcols;
colwidth = dp->maxlen;
if (f_inode)
colwidth += dp->s_inode + 1;
if (f_size) {
if (f_humanize)
colwidth += dp->s_size + 1;
else
colwidth += dp->s_block + 1;
}
if (f_type || f_typedir)
colwidth += 1;
colwidth += 1;
if (termwidth < 2 * colwidth) {
printscol(dp);
return;
}
numcols = termwidth / colwidth;
colwidth = termwidth / numcols; /* spread out if possible */
printtotal(dp); /* "total: %u\n" */
chcnt = col = 0;
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
if (col >= numcols) {
chcnt = col = 0;
(void)putchar('\n');
}
chcnt = printaname(p, dp->s_inode,
f_humanize ? dp->s_size : dp->s_block);
while (chcnt++ < colwidth)
(void)putchar(' ');
col++;
}
(void)putchar('\n');
}
void
printstream(DISPLAY *dp)
{
FTSENT *p;
int col;
int extwidth;
extwidth = 0;
if (f_inode)
extwidth += dp->s_inode + 1;
if (f_size) {
if (f_humanize)
extwidth += dp->s_size + 1;
else
extwidth += dp->s_block + 1;
}
if (f_type)
extwidth += 1;
for (col = 0, p = dp->list; p != NULL; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
if (col > 0) {
(void)putchar(','), col++;
if (col + 1 + extwidth + (int)p->fts_namelen >= termwidth)
(void)putchar('\n'), col = 0;
else
(void)putchar(' '), col++;
}
col += printaname(p, dp->s_inode,
f_humanize ? dp->s_size : dp->s_block);
}
(void)putchar('\n');
}
/*
* print [inode] [size] name
* return # of characters printed, no trailing characters.
*/
static int
printaname(FTSENT *p, int inodefield, int sizefield)
{
struct stat *sp;
int chcnt;
char szbuf[5];
sp = p->fts_statp;
chcnt = 0;
if (f_inode)
chcnt += printf("%*"PRIu64" ", inodefield, sp->st_ino);
if (f_size) {
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size,
"", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
chcnt += printf("%*s ", sizefield, szbuf);
} else {
chcnt += printf(f_commas ? "%'*llu " : "%*llu ",
sizefield, (unsigned long long)
howmany(sp->st_blocks, blocksize));
}
}
if (f_octal || f_octal_escape)
chcnt += safe_printpath(p);
else if (f_nonprint)
chcnt += printescapedpath(p);
else
chcnt += printpath(p);
if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
chcnt += printtype(sp->st_mode);
return (chcnt);
}
static void
printtime(time_t ftime)
{
int i;
const char *longstring;
if ((longstring = ctime(&ftime)) == NULL) {
/* 012345678901234567890123 */
longstring = "????????????????????????";
}
for (i = 4; i < 11; ++i)
(void)putchar(longstring[i]);
#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
if (f_sectime)
for (i = 11; i < 24; i++)
(void)putchar(longstring[i]);
else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
for (i = 11; i < 16; ++i)
(void)putchar(longstring[i]);
else {
(void)putchar(' ');
for (i = 20; i < 24; ++i)
(void)putchar(longstring[i]);
}
(void)putchar(' ');
}
/*
* Display total used disk space in the form "total: %u\n".
* Note: POSIX (IEEE Std 1003.1-2001) says this should be always in 512 blocks,
* but we humanise it with -h, or separate it with commas with -M, and use 1024
* with -k.
*/
static void
printtotal(DISPLAY *dp)
{
char szbuf[5];
if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf), (int64_t)dp->stotal,
"", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
(void)printf("total %s\n", szbuf);
} else {
(void)printf(f_commas ? "total %'llu\n" :
"total %llu\n", (unsigned long long)
howmany(dp->btotal, blocksize));
}
}
}
static int
printtype(u_int mode)
{
switch (mode & S_IFMT) {
case S_IFDIR:
(void)putchar('/');
return (1);
case S_IFIFO:
(void)putchar('|');
return (1);
case S_IFLNK:
(void)putchar('@');
return (1);
case S_IFSOCK:
(void)putchar('=');
return (1);
case S_IFWHT:
(void)putchar('%');
return (1);
}
if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
(void)putchar('*');
return (1);
}
return (0);
}
static void
printlink(FTSENT *p)
{
int lnklen;
char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
if (p->fts_level == FTS_ROOTLEVEL)
(void)snprintf(name, sizeof(name), "%s", p->fts_name);
else
(void)snprintf(name, sizeof(name),
"%s/%s", p->fts_parent->fts_accpath, p->fts_name);
if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
(void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
return;
}
path[lnklen] = '\0';
(void)printf(" -> ");
if (f_octal || f_octal_escape)
(void)safe_print(path);
else if (f_nonprint)
(void)printescaped(path);
else
(void)printf("%s", path);
}

View File

@ -0,0 +1,181 @@
/* $NetBSD: stat_flags.c,v 1.18 2003/10/27 00:12:41 lukem Exp $ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#else
#define HAVE_STRUCT_STAT_ST_FLAGS 1
#endif
#include <sys/cdefs.h>
#if !defined(lint)
#if 0
static char sccsid[] = "@(#)stat_flags.c 8.2 (Berkeley) 7/28/94";
#else
__RCSID("$NetBSD: stat_flags.c,v 1.18 2003/10/27 00:12:41 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>
#include <stddef.h>
#include <string.h>
#include "stat_flags.h"
#define SAPPEND(s) do { \
if (prefix != NULL) \
(void)strlcat(string, prefix, sizeof(string)); \
(void)strlcat(string, s, sizeof(string)); \
prefix = ","; \
} while (/* CONSTCOND */ 0)
/*
* flags_to_string --
* Convert stat flags to a comma-separated string. If no flags
* are set, return the default string.
*/
char *
flags_to_string(u_long flags, const char *def)
{
static char string[128];
const char *prefix;
string[0] = '\0';
prefix = NULL;
#if HAVE_STRUCT_STAT_ST_FLAGS
if (flags & UF_APPEND)
SAPPEND("uappnd");
if (flags & UF_IMMUTABLE)
SAPPEND("uchg");
if (flags & UF_NODUMP)
SAPPEND("nodump");
if (flags & UF_OPAQUE)
SAPPEND("opaque");
if (flags & SF_APPEND)
SAPPEND("sappnd");
if (flags & SF_ARCHIVED)
SAPPEND("arch");
if (flags & SF_IMMUTABLE)
SAPPEND("schg");
#endif
if (prefix == NULL)
strlcpy(string, def, sizeof(string));
return (string);
}
#define TEST(a, b, f) { \
if (!strcmp(a, b)) { \
if (clear) { \
if (clrp) \
*clrp |= (f); \
if (setp) \
*setp &= ~(f); \
} else { \
if (setp) \
*setp |= (f); \
if (clrp) \
*clrp &= ~(f); \
} \
break; \
} \
}
/*
* string_to_flags --
* Take string of arguments and return stat flags. Return 0 on
* success, 1 on failure. On failure, stringp is set to point
* to the offending token.
*/
int
string_to_flags(char **stringp, u_long *setp, u_long *clrp)
{
int clear;
char *string, *p;
if (setp)
*setp = 0;
if (clrp)
*clrp = 0;
#if HAVE_STRUCT_STAT_ST_FLAGS
string = *stringp;
while ((p = strsep(&string, "\t ,")) != NULL) {
clear = 0;
*stringp = p;
if (*p == '\0')
continue;
if (p[0] == 'n' && p[1] == 'o') {
clear = 1;
p += 2;
}
switch (p[0]) {
case 'a':
TEST(p, "arch", SF_ARCHIVED);
TEST(p, "archived", SF_ARCHIVED);
return (1);
case 'd':
clear = !clear;
TEST(p, "dump", UF_NODUMP);
return (1);
case 'n':
/*
* Support `nonodump'. Note that
* the state of clear is not changed.
*/
TEST(p, "nodump", UF_NODUMP);
return (1);
case 'o':
TEST(p, "opaque", UF_OPAQUE);
return (1);
case 's':
TEST(p, "sappnd", SF_APPEND);
TEST(p, "sappend", SF_APPEND);
TEST(p, "schg", SF_IMMUTABLE);
TEST(p, "schange", SF_IMMUTABLE);
TEST(p, "simmutable", SF_IMMUTABLE);
return (1);
case 'u':
TEST(p, "uappnd", UF_APPEND);
TEST(p, "uappend", UF_APPEND);
TEST(p, "uchg", UF_IMMUTABLE);
TEST(p, "uchange", UF_IMMUTABLE);
TEST(p, "uimmutable", UF_IMMUTABLE);
return (1);
default:
return (1);
}
}
#endif
return (0);
}

View File

@ -0,0 +1,39 @@
/* $NetBSD: stat_flags.h,v 1.4 2003/08/07 09:05:16 agc Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
*/
char *flags_to_string(u_long, const char *);
int string_to_flags(char **, u_long *, u_long *);
#define DEFAULT_MODE 0644

View File

@ -0,0 +1,168 @@
/* $NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)util.c 8.5 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <err.h>
#include <fts.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vis.h>
#include <wchar.h>
#include <wctype.h>
#include "ls.h"
#include "extern.h"
int
safe_print(const char *src)
{
size_t len;
char *name;
int flags;
flags = VIS_NL | VIS_OCTAL | VIS_WHITE;
if (f_octal_escape)
flags |= VIS_CSTYLE;
len = strlen(src);
if (len != 0 && SIZE_T_MAX/len <= 4) {
errx(EXIT_FAILURE, "%s: name too long", src);
/* NOTREACHED */
}
name = (char *)malloc(4*len+1);
if (name != NULL) {
len = strvis(name, src, flags);
(void)printf("%s", name);
free(name);
return len;
} else
errx(EXIT_FAILURE, "out of memory!");
/* NOTREACHED */
}
/*
* The reasons why we don't use putwchar(wc) here are:
* - If wc == L'\0', we need to restore the initial shift state, but
* the C language standard doesn't say that putwchar(L'\0') does.
* - It isn't portable to mix a wide-oriented function (i.e. getwchar)
* with byte-oriented functions (printf et al.) in same FILE.
*/
static int
printwc(wchar_t wc, mbstate_t *pst)
{
size_t size;
char buf[MB_LEN_MAX];
size = wcrtomb(buf, wc, pst);
if (size == (size_t)-1) /* This shouldn't happen, but for sure */
return 0;
if (wc == L'\0') {
/* The following condition must be always true, but for sure */
if (size > 0 && buf[size - 1] == '\0')
--size;
}
if (size > 0)
fwrite(buf, 1, size, stdout);
return wc == L'\0' ? 0 : wcwidth(wc);
}
int
printescaped(const char *src)
{
int n = 0;
mbstate_t src_state, stdout_state;
/* The following +1 is to pass '\0' at the end of src to mbrtowc(). */
const char *endptr = src + strlen(src) + 1;
/*
* We have to reset src_state each time in this function, because
* the codeset of src pathname may not match with current locale.
* Note that if we pass NULL instead of src_state to mbrtowc(),
* there is no way to reset the state.
*/
memset(&src_state, 0, sizeof(src_state));
memset(&stdout_state, 0, sizeof(stdout_state));
while (src < endptr) {
wchar_t wc;
size_t rv, span = endptr - src;
#if 0
/*
* XXX - we should fix libc instead.
* Theoretically this should work, but our current
* implementation of iso2022 module doesn't actually work
* as expected, if there are redundant escape sequences
* which exceed 32 bytes.
*/
if (span > MB_CUR_MAX)
span = MB_CUR_MAX;
#endif
rv = mbrtowc(&wc, src, span, &src_state);
if (rv == 0) { /* assert(wc == L'\0'); */
/* The following may output a shift sequence. */
n += printwc(wc, &stdout_state);
break;
}
if (rv == (size_t)-1) { /* probably errno == EILSEQ */
n += printwc(L'?', &stdout_state);
/* try to skip 1byte, because there is no better way */
src++;
memset(&src_state, 0, sizeof(src_state));
} else if (rv == (size_t)-2) {
if (span < MB_CUR_MAX) { /* incomplete char */
n += printwc(L'?', &stdout_state);
break;
}
src += span; /* a redundant shift sequence? */
} else {
n += printwc(iswprint(wc) ? wc : L'?', &stdout_state);
src += rv;
}
}
return n;
}

View File

@ -0,0 +1,19 @@
# A slightly better Makefile. Let's define a "suffix rule" to
# create object files from source files.
# Let's also introduce the concept of variables.
PROG= ls
OBJS= cmp.o ls.o main.o print.o stat_flags.o util.o
CFLAGS= -Wall -g
all: ${PROG}
depend:
mkdep -- ${CFLAGS} *.c
${PROG}: ${OBJS}
@echo $@ depends on $?
${CC} ${OBJS} -o ${PROG} ${LDFLAGS}
clean:
rm -f ${PROG} ${OBJS}

View File

@ -0,0 +1,209 @@
/* $NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cmp.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>
#include <string.h>
#include "ls.h"
#include "extern.h"
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \
defined(_XOPEN_SOURCE) || defined(__NetBSD__)
#define ATIMENSEC_CMP(x, op, y) ((x)->st_atimensec op (y)->st_atimensec)
#define CTIMENSEC_CMP(x, op, y) ((x)->st_ctimensec op (y)->st_ctimensec)
#define MTIMENSEC_CMP(x, op, y) ((x)->st_mtimensec op (y)->st_mtimensec)
#else
#define ATIMENSEC_CMP(x, op, y) \
((x)->st_atimespec.tv_nsec op (y)->st_atimespec.tv_nsec)
#define CTIMENSEC_CMP(x, op, y) \
((x)->st_ctimespec.tv_nsec op (y)->st_ctimespec.tv_nsec)
#define MTIMENSEC_CMP(x, op, y) \
((x)->st_mtimespec.tv_nsec op (y)->st_mtimespec.tv_nsec)
#endif
int
namecmp(const FTSENT *a, const FTSENT *b)
{
return (strcmp(a->fts_name, b->fts_name));
}
int
revnamecmp(const FTSENT *a, const FTSENT *b)
{
return (strcmp(b->fts_name, a->fts_name));
}
int
modcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
return (1);
else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
return (-1);
else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (1);
else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (-1);
else
return (namecmp(a, b));
}
int
revmodcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_mtime > a->fts_statp->st_mtime)
return (-1);
else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime)
return (1);
else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (-1);
else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (1);
else
return (revnamecmp(a, b));
}
int
acccmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_atime > a->fts_statp->st_atime)
return (1);
else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
return (-1);
else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (1);
else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (-1);
else
return (namecmp(a, b));
}
int
revacccmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_atime > a->fts_statp->st_atime)
return (-1);
else if (b->fts_statp->st_atime < a->fts_statp->st_atime)
return (1);
else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (-1);
else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (1);
else
return (revnamecmp(a, b));
}
int
statcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
return (1);
else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
return (-1);
else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (1);
else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (-1);
else
return (namecmp(a, b));
}
int
revstatcmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_ctime > a->fts_statp->st_ctime)
return (-1);
else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime)
return (1);
else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp))
return (-1);
else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp))
return (1);
else
return (revnamecmp(a, b));
}
int
sizecmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_size > a->fts_statp->st_size)
return (1);
if (b->fts_statp->st_size < a->fts_statp->st_size)
return (-1);
else
return (namecmp(a, b));
}
int
revsizecmp(const FTSENT *a, const FTSENT *b)
{
if (b->fts_statp->st_size > a->fts_statp->st_size)
return (-1);
if (b->fts_statp->st_size < a->fts_statp->st_size)
return (1);
else
return (revnamecmp(a, b));
}
#if 0
int
sillysort(const FTSENT *a, const FTSENT *b)
{
(void)a; (void)b;
int n[3] = { -1, 0, 1 };
return n[((long)&n)%3];
}
#endif

View File

@ -0,0 +1,53 @@
/* $NetBSD: extern.h,v 1.17 2011/08/29 14:44:21 joerg Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
*/
int acccmp(const FTSENT *, const FTSENT *);
int revacccmp(const FTSENT *, const FTSENT *);
int modcmp(const FTSENT *, const FTSENT *);
int revmodcmp(const FTSENT *, const FTSENT *);
int namecmp(const FTSENT *, const FTSENT *);
int revnamecmp(const FTSENT *, const FTSENT *);
int statcmp(const FTSENT *, const FTSENT *);
int revstatcmp(const FTSENT *, const FTSENT *);
int sizecmp(const FTSENT *, const FTSENT *);
int revsizecmp(const FTSENT *, const FTSENT *);
int ls_main(int, char *[]);
int printescaped(const char *);
void printacol(DISPLAY *);
void printcol(DISPLAY *);
void printlong(DISPLAY *);
void printscol(DISPLAY *);
void printstream(DISPLAY *);
int safe_print(const char *);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,81 @@
/* $NetBSD: ls.h,v 1.19 2014/02/20 18:56:36 christos Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ls.h 8.1 (Berkeley) 5/31/93
*/
#define NO_PRINT 1
extern long blocksize; /* block size units */
extern int f_accesstime; /* use time of last access */
extern int f_flags; /* show flags associated with a file */
extern int f_grouponly; /* long listing without owner */
extern int f_humanize; /* humanize size field */
extern int f_commas; /* separate size field with commas */
extern int f_inode; /* print inode */
extern int f_longform; /* long listing format */
extern int f_octal; /* print octal escapes for nongraphic characters */
extern int f_octal_escape; /* like f_octal but use C escapes if possible */
extern int f_sectime; /* print the real time for all files */
extern int f_size; /* list size in short listing */
extern int f_statustime; /* use time of last mode change */
extern int f_type; /* add type character for non-regular files */
extern int f_typedir; /* add type character for directories */
extern int f_nonprint; /* show unprintables as ? */
extern int f_fullpath; /* print full pathname, not filename */
extern int f_leafonly; /* when recursing, print leaf names only */
typedef struct {
FTSENT *list;
u_int64_t btotal;
u_int64_t stotal;
int entries;
unsigned int maxlen;
int s_block;
int s_flags;
int s_group;
int s_inode;
int s_nlink;
int s_size;
int s_user;
int s_major;
int s_minor;
} DISPLAY;
typedef struct {
char *user;
char *group;
char *flags;
char data[1];
} NAMES;

View File

@ -0,0 +1,51 @@
/* $NetBSD: main.c,v 1.5 2016/09/05 01:00:07 sevan Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: main.c,v 1.5 2016/09/05 01:00:07 sevan Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <fts.h>
#include "ls.h"
#include "extern.h"
#include "stat_flags.h"
int
main(int argc, char *argv[])
{
return ls_main(argc, argv);
/* NOTREACHED */
}

View File

@ -0,0 +1,497 @@
/* $NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
#else
__RCSID("$NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <inttypes.h>
#include <fts.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <tzfile.h>
#include <unistd.h>
#include <util.h>
#include "ls.h"
#include "extern.h"
extern int termwidth;
static int printaname(FTSENT *, int, int);
static void printlink(FTSENT *);
static void printtime(time_t);
static void printtotal(DISPLAY *dp);
static int printtype(u_int);
static time_t now;
#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
static int
safe_printpath(const FTSENT *p) {
int chcnt;
if (f_fullpath) {
chcnt = safe_print(p->fts_path);
chcnt += safe_print("/");
} else
chcnt = 0;
return chcnt + safe_print(p->fts_name);
}
static int
printescapedpath(const FTSENT *p) {
int chcnt;
if (f_fullpath) {
chcnt = printescaped(p->fts_path);
chcnt += printescaped("/");
} else
chcnt = 0;
return chcnt + printescaped(p->fts_name);
}
static int
printpath(const FTSENT *p) {
if (f_fullpath)
return printf("%s/%s", p->fts_path, p->fts_name);
else
return printf("%s", p->fts_name);
}
void
printscol(DISPLAY *dp)
{
FTSENT *p;
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
(void)printaname(p, dp->s_inode, dp->s_block);
(void)putchar('\n');
}
}
void
printlong(DISPLAY *dp)
{
struct stat *sp;
FTSENT *p;
NAMES *np;
char buf[20], szbuf[5];
now = time(NULL);
if (!f_leafonly)
printtotal(dp); /* "total: %u\n" */
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
sp = p->fts_statp;
if (f_inode)
(void)printf("%*"PRIu64" ", dp->s_inode, sp->st_ino);
if (f_size) {
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf),
sp->st_blocks * S_BLKSIZE,
"", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
(void)printf("%*s ", dp->s_block, szbuf);
} else {
(void)printf(f_commas ? "%'*llu " : "%*llu ",
dp->s_block,
(unsigned long long)howmany(sp->st_blocks,
blocksize));
}
}
(void)strmode(sp->st_mode, buf);
np = p->fts_pointer;
(void)printf("%s %*lu ", buf, dp->s_nlink,
(unsigned long)sp->st_nlink);
if (!f_grouponly)
(void)printf("%-*s ", dp->s_user, np->user);
(void)printf("%-*s ", dp->s_group, np->group);
if (f_flags)
(void)printf("%-*s ", dp->s_flags, np->flags);
if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
(void)printf("%*lld, %*lld ",
dp->s_major, (long long)major(sp->st_rdev),
dp->s_minor, (long long)minor(sp->st_rdev));
else
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf),
sp->st_size, "", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
(void)printf("%*s ", dp->s_size, szbuf);
} else {
(void)printf(f_commas ? "%'*llu " : "%*llu ",
dp->s_size, (unsigned long long)
sp->st_size);
}
if (f_accesstime)
printtime(sp->st_atime);
else if (f_statustime)
printtime(sp->st_ctime);
else
printtime(sp->st_mtime);
if (f_octal || f_octal_escape)
(void)safe_printpath(p);
else if (f_nonprint)
(void)printescapedpath(p);
else
(void)printpath(p);
if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
(void)printtype(sp->st_mode);
if (S_ISLNK(sp->st_mode))
printlink(p);
(void)putchar('\n');
}
}
void
printcol(DISPLAY *dp)
{
static FTSENT **array;
static int lastentries = -1;
FTSENT *p;
int base, chcnt, col, colwidth, num;
int numcols, numrows, row;
colwidth = dp->maxlen;
if (f_inode)
colwidth += dp->s_inode + 1;
if (f_size) {
if (f_humanize)
colwidth += dp->s_size + 1;
else
colwidth += dp->s_block + 1;
}
if (f_type || f_typedir)
colwidth += 1;
colwidth += 1;
if (termwidth < 2 * colwidth) {
printscol(dp);
return;
}
/*
* Have to do random access in the linked list -- build a table
* of pointers.
*/
if (dp->entries > lastentries) {
FTSENT **newarray;
newarray = realloc(array, dp->entries * sizeof(FTSENT *));
if (newarray == NULL) {
warn(NULL);
printscol(dp);
return;
}
lastentries = dp->entries;
array = newarray;
}
for (p = dp->list, num = 0; p; p = p->fts_link)
if (p->fts_number != NO_PRINT)
array[num++] = p;
numcols = termwidth / colwidth;
colwidth = termwidth / numcols; /* spread out if possible */
numrows = num / numcols;
if (num % numcols)
++numrows;
printtotal(dp); /* "total: %u\n" */
for (row = 0; row < numrows; ++row) {
for (base = row, chcnt = col = 0; col < numcols; ++col) {
chcnt = printaname(array[base], dp->s_inode,
f_humanize ? dp->s_size : dp->s_block);
if ((base += numrows) >= num)
break;
while (chcnt++ < colwidth)
(void)putchar(' ');
}
(void)putchar('\n');
}
}
void
printacol(DISPLAY *dp)
{
FTSENT *p;
int chcnt, col, colwidth;
int numcols;
colwidth = dp->maxlen;
if (f_inode)
colwidth += dp->s_inode + 1;
if (f_size) {
if (f_humanize)
colwidth += dp->s_size + 1;
else
colwidth += dp->s_block + 1;
}
if (f_type || f_typedir)
colwidth += 1;
colwidth += 1;
if (termwidth < 2 * colwidth) {
printscol(dp);
return;
}
numcols = termwidth / colwidth;
colwidth = termwidth / numcols; /* spread out if possible */
printtotal(dp); /* "total: %u\n" */
chcnt = col = 0;
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
if (col >= numcols) {
chcnt = col = 0;
(void)putchar('\n');
}
chcnt = printaname(p, dp->s_inode,
f_humanize ? dp->s_size : dp->s_block);
while (chcnt++ < colwidth)
(void)putchar(' ');
col++;
}
(void)putchar('\n');
}
void
printstream(DISPLAY *dp)
{
FTSENT *p;
int col;
int extwidth;
extwidth = 0;
if (f_inode)
extwidth += dp->s_inode + 1;
if (f_size) {
if (f_humanize)
extwidth += dp->s_size + 1;
else
extwidth += dp->s_block + 1;
}
if (f_type)
extwidth += 1;
for (col = 0, p = dp->list; p != NULL; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
if (col > 0) {
(void)putchar(','), col++;
if (col + 1 + extwidth + (int)p->fts_namelen >= termwidth)
(void)putchar('\n'), col = 0;
else
(void)putchar(' '), col++;
}
col += printaname(p, dp->s_inode,
f_humanize ? dp->s_size : dp->s_block);
}
(void)putchar('\n');
}
/*
* print [inode] [size] name
* return # of characters printed, no trailing characters.
*/
static int
printaname(FTSENT *p, int inodefield, int sizefield)
{
struct stat *sp;
int chcnt;
char szbuf[5];
sp = p->fts_statp;
chcnt = 0;
if (f_inode)
chcnt += printf("%*"PRIu64" ", inodefield, sp->st_ino);
if (f_size) {
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size,
"", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
chcnt += printf("%*s ", sizefield, szbuf);
} else {
chcnt += printf(f_commas ? "%'*llu " : "%*llu ",
sizefield, (unsigned long long)
howmany(sp->st_blocks, blocksize));
}
}
if (f_octal || f_octal_escape)
chcnt += safe_printpath(p);
else if (f_nonprint)
chcnt += printescapedpath(p);
else
chcnt += printpath(p);
if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
chcnt += printtype(sp->st_mode);
return (chcnt);
}
static void
printtime(time_t ftime)
{
int i;
const char *longstring;
if ((longstring = ctime(&ftime)) == NULL) {
/* 012345678901234567890123 */
longstring = "????????????????????????";
}
for (i = 4; i < 11; ++i)
(void)putchar(longstring[i]);
#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
if (f_sectime)
for (i = 11; i < 24; i++)
(void)putchar(longstring[i]);
else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
for (i = 11; i < 16; ++i)
(void)putchar(longstring[i]);
else {
(void)putchar(' ');
for (i = 20; i < 24; ++i)
(void)putchar(longstring[i]);
}
(void)putchar(' ');
}
/*
* Display total used disk space in the form "total: %u\n".
* Note: POSIX (IEEE Std 1003.1-2001) says this should be always in 512 blocks,
* but we humanise it with -h, or separate it with commas with -M, and use 1024
* with -k.
*/
static void
printtotal(DISPLAY *dp)
{
char szbuf[5];
if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
if (f_humanize) {
if ((humanize_number(szbuf, sizeof(szbuf), (int64_t)dp->stotal,
"", HN_AUTOSCALE,
(HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
err(1, "humanize_number");
(void)printf("total %s\n", szbuf);
} else {
(void)printf(f_commas ? "total %'llu\n" :
"total %llu\n", (unsigned long long)
howmany(dp->btotal, blocksize));
}
}
}
static int
printtype(u_int mode)
{
switch (mode & S_IFMT) {
case S_IFDIR:
(void)putchar('/');
return (1);
case S_IFIFO:
(void)putchar('|');
return (1);
case S_IFLNK:
(void)putchar('@');
return (1);
case S_IFSOCK:
(void)putchar('=');
return (1);
case S_IFWHT:
(void)putchar('%');
return (1);
}
if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
(void)putchar('*');
return (1);
}
return (0);
}
static void
printlink(FTSENT *p)
{
int lnklen;
char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
if (p->fts_level == FTS_ROOTLEVEL)
(void)snprintf(name, sizeof(name), "%s", p->fts_name);
else
(void)snprintf(name, sizeof(name),
"%s/%s", p->fts_parent->fts_accpath, p->fts_name);
if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
(void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
return;
}
path[lnklen] = '\0';
(void)printf(" -> ");
if (f_octal || f_octal_escape)
(void)safe_print(path);
else if (f_nonprint)
(void)printescaped(path);
else
(void)printf("%s", path);
}

View File

@ -0,0 +1,181 @@
/* $NetBSD: stat_flags.c,v 1.18 2003/10/27 00:12:41 lukem Exp $ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#else
#define HAVE_STRUCT_STAT_ST_FLAGS 1
#endif
#include <sys/cdefs.h>
#if !defined(lint)
#if 0
static char sccsid[] = "@(#)stat_flags.c 8.2 (Berkeley) 7/28/94";
#else
__RCSID("$NetBSD: stat_flags.c,v 1.18 2003/10/27 00:12:41 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>
#include <stddef.h>
#include <string.h>
#include "stat_flags.h"
#define SAPPEND(s) do { \
if (prefix != NULL) \
(void)strlcat(string, prefix, sizeof(string)); \
(void)strlcat(string, s, sizeof(string)); \
prefix = ","; \
} while (/* CONSTCOND */ 0)
/*
* flags_to_string --
* Convert stat flags to a comma-separated string. If no flags
* are set, return the default string.
*/
char *
flags_to_string(u_long flags, const char *def)
{
static char string[128];
const char *prefix;
string[0] = '\0';
prefix = NULL;
#if HAVE_STRUCT_STAT_ST_FLAGS
if (flags & UF_APPEND)
SAPPEND("uappnd");
if (flags & UF_IMMUTABLE)
SAPPEND("uchg");
if (flags & UF_NODUMP)
SAPPEND("nodump");
if (flags & UF_OPAQUE)
SAPPEND("opaque");
if (flags & SF_APPEND)
SAPPEND("sappnd");
if (flags & SF_ARCHIVED)
SAPPEND("arch");
if (flags & SF_IMMUTABLE)
SAPPEND("schg");
#endif
if (prefix == NULL)
strlcpy(string, def, sizeof(string));
return (string);
}
#define TEST(a, b, f) { \
if (!strcmp(a, b)) { \
if (clear) { \
if (clrp) \
*clrp |= (f); \
if (setp) \
*setp &= ~(f); \
} else { \
if (setp) \
*setp |= (f); \
if (clrp) \
*clrp &= ~(f); \
} \
break; \
} \
}
/*
* string_to_flags --
* Take string of arguments and return stat flags. Return 0 on
* success, 1 on failure. On failure, stringp is set to point
* to the offending token.
*/
int
string_to_flags(char **stringp, u_long *setp, u_long *clrp)
{
int clear;
char *string, *p;
if (setp)
*setp = 0;
if (clrp)
*clrp = 0;
#if HAVE_STRUCT_STAT_ST_FLAGS
string = *stringp;
while ((p = strsep(&string, "\t ,")) != NULL) {
clear = 0;
*stringp = p;
if (*p == '\0')
continue;
if (p[0] == 'n' && p[1] == 'o') {
clear = 1;
p += 2;
}
switch (p[0]) {
case 'a':
TEST(p, "arch", SF_ARCHIVED);
TEST(p, "archived", SF_ARCHIVED);
return (1);
case 'd':
clear = !clear;
TEST(p, "dump", UF_NODUMP);
return (1);
case 'n':
/*
* Support `nonodump'. Note that
* the state of clear is not changed.
*/
TEST(p, "nodump", UF_NODUMP);
return (1);
case 'o':
TEST(p, "opaque", UF_OPAQUE);
return (1);
case 's':
TEST(p, "sappnd", SF_APPEND);
TEST(p, "sappend", SF_APPEND);
TEST(p, "schg", SF_IMMUTABLE);
TEST(p, "schange", SF_IMMUTABLE);
TEST(p, "simmutable", SF_IMMUTABLE);
return (1);
case 'u':
TEST(p, "uappnd", UF_APPEND);
TEST(p, "uappend", UF_APPEND);
TEST(p, "uchg", UF_IMMUTABLE);
TEST(p, "uchange", UF_IMMUTABLE);
TEST(p, "uimmutable", UF_IMMUTABLE);
return (1);
default:
return (1);
}
}
#endif
return (0);
}

View File

@ -0,0 +1,39 @@
/* $NetBSD: stat_flags.h,v 1.4 2003/08/07 09:05:16 agc Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.1 (Berkeley) 5/31/93
*/
char *flags_to_string(u_long, const char *);
int string_to_flags(char **, u_long *, u_long *);
#define DEFAULT_MODE 0644

View File

@ -0,0 +1,168 @@
/* $NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Michael Fischbein.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)util.c 8.5 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <err.h>
#include <fts.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vis.h>
#include <wchar.h>
#include <wctype.h>
#include "ls.h"
#include "extern.h"
int
safe_print(const char *src)
{
size_t len;
char *name;
int flags;
flags = VIS_NL | VIS_OCTAL | VIS_WHITE;
if (f_octal_escape)
flags |= VIS_CSTYLE;
len = strlen(src);
if (len != 0 && SIZE_T_MAX/len <= 4) {
errx(EXIT_FAILURE, "%s: name too long", src);
/* NOTREACHED */
}
name = (char *)malloc(4*len+1);
if (name != NULL) {
len = strvis(name, src, flags);
(void)printf("%s", name);
free(name);
return len;
} else
errx(EXIT_FAILURE, "out of memory!");
/* NOTREACHED */
}
/*
* The reasons why we don't use putwchar(wc) here are:
* - If wc == L'\0', we need to restore the initial shift state, but
* the C language standard doesn't say that putwchar(L'\0') does.
* - It isn't portable to mix a wide-oriented function (i.e. getwchar)
* with byte-oriented functions (printf et al.) in same FILE.
*/
static int
printwc(wchar_t wc, mbstate_t *pst)
{
size_t size;
char buf[MB_LEN_MAX];
size = wcrtomb(buf, wc, pst);
if (size == (size_t)-1) /* This shouldn't happen, but for sure */
return 0;
if (wc == L'\0') {
/* The following condition must be always true, but for sure */
if (size > 0 && buf[size - 1] == '\0')
--size;
}
if (size > 0)
fwrite(buf, 1, size, stdout);
return wc == L'\0' ? 0 : wcwidth(wc);
}
int
printescaped(const char *src)
{
int n = 0;
mbstate_t src_state, stdout_state;
/* The following +1 is to pass '\0' at the end of src to mbrtowc(). */
const char *endptr = src + strlen(src) + 1;
/*
* We have to reset src_state each time in this function, because
* the codeset of src pathname may not match with current locale.
* Note that if we pass NULL instead of src_state to mbrtowc(),
* there is no way to reset the state.
*/
memset(&src_state, 0, sizeof(src_state));
memset(&stdout_state, 0, sizeof(stdout_state));
while (src < endptr) {
wchar_t wc;
size_t rv, span = endptr - src;
#if 0
/*
* XXX - we should fix libc instead.
* Theoretically this should work, but our current
* implementation of iso2022 module doesn't actually work
* as expected, if there are redundant escape sequences
* which exceed 32 bytes.
*/
if (span > MB_CUR_MAX)
span = MB_CUR_MAX;
#endif
rv = mbrtowc(&wc, src, span, &src_state);
if (rv == 0) { /* assert(wc == L'\0'); */
/* The following may output a shift sequence. */
n += printwc(wc, &stdout_state);
break;
}
if (rv == (size_t)-1) { /* probably errno == EILSEQ */
n += printwc(L'?', &stdout_state);
/* try to skip 1byte, because there is no better way */
src++;
memset(&src_state, 0, sizeof(src_state));
} else if (rv == (size_t)-2) {
if (span < MB_CUR_MAX) { /* incomplete char */
n += printwc(L'?', &stdout_state);
break;
}
src += span; /* a redundant shift sequence? */
} else {
n += printwc(iswprint(wc) ? wc : L'?', &stdout_state);
src += rv;
}
}
return n;
}

View File

@ -0,0 +1,49 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* A simple program to show what arguments were passed to a program. This
* can be used to illustrate how different shells expand arguments
* differently.
*
* See also:
* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
* https://wpollock.com/ShScript/CmdLineProcessing.htm
*
* Examples:
* ./a.out
* ./a.out *.c
* ./a.out *.none
* ./a.out *.[1c]
* ./a.out "*.c"
* ./a.out $USER
* ./a.out "$(echo *.1)"
* ./a.out {foo,bar,baz}.whatever
* ./a.out {1..5}
* ./a.out {1..5}{a..f}
*/
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char **argv) {
int i;
for (i=0; i<argc; i++) {
printf("%s\n", argv[i]);
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,22 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
int main() {
int n;
while(1) {
n++;
}
return n;
}

View File

@ -0,0 +1,46 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
#include <stdlib.h>
int a;
char *s;
char buf[1024];
int
main(int argc, char **argv) {
int *b;
char *string = "abcd";
*b = 7;
printf("b at : 0x%12lX\n", (unsigned long)&b);
printf("b at : 0x%12lX\n", (unsigned long)&(*b));
#if 0
printf("main (function) at : 0x%12lX\n", (unsigned long)&main);
printf("argc at : 0x%12lX\n", (unsigned long)&argc);
printf("argv at : 0x%12lX\n", (unsigned long)&argv);
printf("argv[0] at : 0x%12lX\n", (unsigned long)&argv[0]);
printf("a at : 0x%12lX\n", (unsigned long)&a);
printf("s at : 0x%12lX\n", (unsigned long)&s);
printf("buf at : 0x%12lX\n", (unsigned long)&buf);
printf("string at : 0x%12lX\n", (unsigned long)&string);
printf("fixed string at : 0x%12lX\n", (unsigned long)&(*string));
#endif
return 0;
}

View File

@ -0,0 +1,56 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/*
* Show the difference between placements of the const keyword.
*
* Note: you will get errors compiling this code.
*/
#include <stdio.h>
char * const foo[] = {
"one",
"two",
"three",
NULL
};
const char *bar[] = {
"one",
"two",
"three",
NULL
};
int main() {
/* You can do this, because 'one' is not 'const'... */
foo[0][1] = 'w';
/* ...but your compiler will complain here, because the
* 'foo' itself is 'const *'. */
foo[0] = "blah blah blah";
/* For 'bar', this is reversed: each element in the array
* is const, so we can't change them... */
bar[0][1] = 'w';
/* ...but because 'bar' is not const, we can change what
* this points to. */
bar[0] = "blah blah blah";
return 1;
}

View File

@ -0,0 +1,65 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This program can be used to illustrates how the kernel sets up the
* startup routine. Call with "-e" to specify any of the functions as the
* entry point instead of 'main'; compare otool(1)/objdump(1) output and
* exit codes.
*
* To display the entry point of the program:
* NetBSD:
* - readelf -h a.out | grep ntry
* - objdump -d a.out
*
* Mac OS X:
* - otool -l a.out | grep ntry # decimal address
* - otool -v -t a.out # hex address
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
bar(void) {
printf("bar rules!\n");
exit(EXIT_FAILURE);
/* Unlike foo(), this will not cause a segfault, since we are not
* returning; we explicitly call exit(3). */
}
int
foo(void) {
printf("Foo for the win!\n");
return EXIT_FAILURE;
/* Note: this will cause a segfault on NetBSD, because this function
* returns, but there is nothing to return to: the routines set up
* by the kernel remain set up for 'main', we just told the linker
* to jump into 'foo' at program start. Compare objdump(1)
* output.
* Note: on OS X, we do not segfault! */
}
int
main(int argc, char **argv) {
(void)argc;
(void)argv;
printf("main is at 0x%lX\n", (unsigned long)&main);
/* Note that we do explicitly _not_ return an error here, nor call
* any of the exit(3) functions. Your compiler may warn you
* about this. We're also not casting the return value of printf(3)
* to void. Inspect the return value. */
}

View File

@ -0,0 +1,21 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
int
main(int argc, char **argv) {
printf("main is at 0x%lX\n", (unsigned long)&main);
}

View File

@ -0,0 +1,28 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
#include <stdlib.h>
int
foo(void) {
(void)printf("Who needs 'main'?\n");
return EXIT_FAILURE;
}
int
main(int argc, char **argv) {
printf("main is at 0x%lX\n", (unsigned long)&main);
}

View File

@ -0,0 +1,34 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
#include <stdlib.h>
int
bar(void) {
(void)printf("Look, Ma: no main!\n");
exit(EXIT_FAILURE);
}
int
foo(void) {
(void)printf("Who needs 'main'?\n");
return EXIT_FAILURE;
}
int
main(int argc, char **argv) {
printf("main is at 0x%lX\n", (unsigned long)&main);
}

View File

@ -0,0 +1,23 @@
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
#include <stdio.h>
int
main() {
int n;
n = printf("main is at 0x%lX\n", (unsigned long)&main);
return n;
}

Some files were not shown because too many files have changed in this diff Show More