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