Initial commit
This commit is contained in:
commit
129a4ecbc9
|
@ -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
|
Binary file not shown.
|
@ -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: Can’t fork: %s\n", strerror(errno));
|
||||
continue;
|
||||
} else if (pid == 0) {
|
||||
execlp(buf, buf, (char *)0);
|
||||
fprintf(stderr, "SHELL: Can’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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -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. */
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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) {$/
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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)/
|
|
@ -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.
|
@ -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;
|
||||
}
|
|
@ -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.
|
@ -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"
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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}
|
|
@ -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
|
|
@ -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}
|
|
@ -0,0 +1,2 @@
|
|||
all:
|
||||
cc ${CFLAGS} *.c
|
Binary file not shown.
|
@ -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
|
|
@ -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
|
@ -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;
|
|
@ -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 */
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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}
|
|
@ -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
|
|
@ -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
|
@ -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;
|
|
@ -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 */
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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. */
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue