Alright, I will start by showing what I'm trying to do, and then I'll ask a couple of questions:
I'm trying to create a small tool (similar to the standard
I have a main .c file I compiled using clang, like so:
This is the source of the apue.c header file:
Now, all is well with the compilation process, I don't get any errors or warnings. But, when I try to run my myls I get this error: PR Segmentation fault (core dumped) . I ran
If I run my application
Questions:
1. What am I missing about this book example? Why do I get the fragmentation error?
2. What are the minimum header files necessary to create a simple CLI based application in FreeBSD, say for counting the total number of files in a folder? I've noticed that in the apue.h there are several system calls corresponding to multiple operating systems.
3. I'd like to be able to find a few examples to get started with C dev. in FreeBSD. What books/tutorials do you guys recommend ?
I'm trying to create a small tool (similar to the standard
ls
CLI) trying to learn a few new things about UNIX C programming under BSD. I'm following a book I won't reveal here (not sure if sharing its title would actually infringe forum's regulations (please correct me if I'm wrong)).I have a main .c file I compiled using clang, like so:
cc -o myls ftest.c
, the source of my ftest.c file looks like this:
Code:
#include "apue.h"
#include <dirent.h>
int main(int argc, char *argv[]) {
DIR *dp;
struct dirent *dirp;
if (argc != 2)
// err_quit("usage: ls directory_name");
if ((dp = opendir(argv[1])) == NULL)
// err_sys("can't open %s", argv[1]);
while ((dirp = readdir(dp)) != NULL)
printf("%s\n", dirp->d_name);
closedir(dp);
exit(0);
}
This is the source of the apue.c header file:
Code:
/*
* Our own header, to be included before all standard system headers.
*/
#ifndef _APUE_H
#define _APUE_H
#define _POSIX_C_SOURCE 200809L
#if defined(SOLARIS) /* Solaris 10 */
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 700
#endif
#include <sys/types.h> /* some systems still require this */
#include <sys/stat.h>
#include <termios.h> /* for winsize */
#if defined(MACOS) || !defined(TIOCGWINSZ)
#include <sys/ioctl.h>
#endif
#include <stdio.h> /* for convenience */
#include <stdlib.h> /* for convenience */
#include <stddef.h> /* for offsetof */
#include <string.h> /* for convenience */
#include <unistd.h> /* for convenience */
#include <signal.h> /* for SIG_ERR */
#define MAXLINE 4096 /* max line length */
/*
* Default file access permissions for new files.
*/
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
/*
* Default permissions for new directories.
*/
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
typedef void Sigfunc(int); /* for signal handlers */
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
/*
* Prototypes for our own functions.
*/
char *path_alloc(size_t *); /* {Prog pathalloc} */
long open_max(void); /* {Prog openmax} */
int set_cloexec(int); /* {Prog setfd} */
void clr_fl(int, int);
void set_fl(int, int); /* {Prog setfl} */
void pr_exit(int); /* {Prog prexit} */
void pr_mask(const char *); /* {Prog prmask} */
Sigfunc *signal_intr(int, Sigfunc *); /* {Prog signal_intr_function} */
void daemonize(const char *); /* {Prog daemoninit} */
void sleep_us(unsigned int); /* {Ex sleepus} */
ssize_t readn(int, void *, size_t); /* {Prog readn_writen} */
ssize_t writen(int, const void *, size_t); /* {Prog readn_writen} */
int fd_pipe(int *); /* {Prog sock_fdpipe} */
int recv_fd(int, ssize_t (*func)(int,
const void *, size_t)); /* {Prog recvfd_sockets} */
int send_fd(int, int); /* {Prog sendfd_sockets} */
int send_err(int, int,
const char *); /* {Prog senderr} */
int serv_listen(const char *); /* {Prog servlisten_sockets} */
int serv_accept(int, uid_t *); /* {Prog servaccept_sockets} */
int cli_conn(const char *); /* {Prog cliconn_sockets} */
int buf_args(char *, int (*func)(int,
char **)); /* {Prog bufargs} */
int tty_cbreak(int); /* {Prog raw} */
int tty_raw(int); /* {Prog raw} */
int tty_reset(int); /* {Prog raw} */
void tty_atexit(void); /* {Prog raw} */
struct termios *tty_termios(void); /* {Prog raw} */
int ptym_open(char *, int); /* {Prog ptyopen} */
int ptys_open(char *); /* {Prog ptyopen} */
#ifdef TIOCGWINSZ
pid_t pty_fork(int *, char *, int, const struct termios *,
const struct winsize *); /* {Prog ptyfork} */
#endif
int lock_reg(int, int, int, off_t, int, off_t); /* {Prog lockreg} */
#define read_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
#define readw_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
#define write_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
#define writew_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
#define un_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))
pid_t lock_test(int, int, off_t, int, off_t); /* {Prog locktest} */
#define is_read_lockable(fd, offset, whence, len) \
(lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)
#define is_write_lockable(fd, offset, whence, len) \
(lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0)
void err_msg(const char *, ...); /* {App misc_source} */
void err_dump(const char *, ...) __attribute__((noreturn));
void err_quit(const char *, ...) __attribute__((noreturn));
void err_cont(int, const char *, ...);
void err_exit(int, const char *, ...) __attribute__((noreturn));
void err_ret(const char *, ...);
void err_sys(const char *, ...) __attribute__((noreturn));
void log_msg(const char *, ...); /* {App misc_source} */
void log_open(const char *, int, int);
void log_quit(const char *, ...) __attribute__((noreturn));
void log_ret(const char *, ...);
void log_sys(const char *, ...) __attribute__((noreturn));
void log_exit(int, const char *, ...) __attribute__((noreturn));
void TELL_WAIT(void); /* parent/child from {Sec race_conditions} */
void TELL_PARENT(pid_t);
void TELL_CHILD(pid_t);
void WAIT_PARENT(void);
void WAIT_CHILD(void);
#endif /* _APUE_H */
Now, all is well with the compilation process, I don't get any errors or warnings. But, when I try to run my myls I get this error: PR Segmentation fault (core dumped) . I ran
truss ./myls
and this is what I get back
Code:
mmap(0x0,32768,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34366136320 (0x80061a000)
issetugid(0x800819f30,0x7fffffffefca,0x40,0x0,0xffff80080081af66,0x0) = 0 (0x0)
lstat("/etc",{ mode=drwxr-xr-x ,inode=2808960,size=2048,blksize=32768 }) = 0 (0x0)
lstat("/etc/libmap.conf",{ mode=-rw-r--r-- ,inode=2809041,size=112,blksize=32768 }) = 0 (0x0)
open("/etc/libmap.conf",O_CLOEXEC,01760) = 3 (0x3)
fstat(3,{ mode=-rw-r--r-- ,inode=2809041,size=112,blksize=32768 }) = 0 (0x0)
mmap(0x0,112,PROT_READ,MAP_PRIVATE,3,0x0) = 34366169088 (0x800622000)
close(3) = 0 (0x0)
lstat("/usr",{ mode=drwxr-xr-x ,inode=8828160,size=512,blksize=32768 }) = 0 (0x0)
lstat("/usr/local",{ mode=drwxr-xr-x ,inode=8828171,size=512,blksize=32768 }) = 0 (0x0)
lstat("/usr/local/etc",{ mode=drwxr-xr-x ,inode=9000309,size=1024,blksize=32768 }) = 0 (0x0)
lstat("/usr/local/etc/libmap.d",0x7fffffffb7b8) ERR#2 'No such file or directory'
munmap(0x800622000,112) = 0 (0x0)
open("/var/run/ld-elf.so.hints",O_CLOEXEC,00) = 3 (0x3)
read(3,"Ehnt\^A\0\0\0\M^@\0\0\0X\0\0\0\0"...,128) = 128 (0x80)
lseek(3,0x80,SEEK_SET) = 128 (0x80)
read(3,"/lib:/usr/lib:/usr/lib/compat:/u"...,88) = 88 (0x58)
close(3) = 0 (0x0)
access("/lib/libc.so.7",0) = 0 (0x0)
open("/lib/libc.so.7",O_CLOEXEC,030363770) = 3 (0x3)
fstat(3,{ mode=-r--r--r-- ,inode=12118669,size=1567216,blksize=32768 }) = 0 (0x0)
mmap(0x0,4096,PROT_READ,MAP_PRIVATE|MAP_PREFAULT_READ,3,0x0) = 34366169088 (0x800622000)
mmap(0x0,3772416,PROT_NONE,MAP_PRIVATE|MAP_ANON|MAP_NOCORE,-1,0x0) = 34368237568 (0x80081b000)
mmap(0x80081b000,1458176,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_FIXED|MAP_NOCORE|MAP_PREFAULT_READ,3,0x0) = 34368237568 (0x80081b000)
mmap(0x800b7f000,49152,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_PREFAULT_READ,3,0x164000) = 34371792896 (0x800b7f000)
mmap(0x800b8b000,167936,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_ANON,-1,0x0) = 34371842048 (0x800b8b000)
munmap(0x800622000,4096) = 0 (0x0)
close(3) = 0 (0x0)
munmap(0x800621000,4096) = 0 (0x0)
mmap(0x0,102400,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34366164992 (0x800621000)
sysarch(0x81,0x7fffffffd1a8,0x4,0x0,0xffffffffffab4080,0x8080808080808080) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0) = 0 (0x0)
readlink("/etc/malloc.conf",0x7fffffffc8d0,1024) ERR#2 'No such file or directory'
issetugid(0x80095693e,0x7fffffffc8d0,0xffffffffffffffff,0x0,0x3a,0xffffffff0fffffff) = 0 (0x0)
mmap(0x0,4194304,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34372009984 (0x800bb4000)
munmap(0x800bb4000,4194304) = 0 (0x0)
mmap(0x0,8384512,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34372009984 (0x800bb4000)
munmap(0x800bb4000,311296) = 0 (0x0)
munmap(0x801000000,3878912) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0) = 0 (0x0)
open("(null)",O_NONBLOCK|O_DIRECTORY|O_CLOEXEC,037777756020) ERR#14 'Bad address
If I run my application
sudo ./myls /<whatever_folder>
I don't get the error message anymore, but nothing shows up. It seems like the input-stream is not working properly since what this application is supposed to do is to receive an argument as the param.<dir_name> and output a list with the content of that particular folder.Questions:
1. What am I missing about this book example? Why do I get the fragmentation error?
2. What are the minimum header files necessary to create a simple CLI based application in FreeBSD, say for counting the total number of files in a folder? I've noticed that in the apue.h there are several system calls corresponding to multiple operating systems.
3. I'd like to be able to find a few examples to get started with C dev. in FreeBSD. What books/tutorials do you guys recommend ?