#ifndef _APUE_H
#define _APUE_H

#include <stdarg.h>  

#define _XOPEN_SOURCE 600

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/termios.h>
#ifndef TIOCGWINSZ
#include <sys/ioctl.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#define MAXLINE 4096

#define FILE_MODE    (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define DIR_MODE     (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)

typedef void Sigfunc(int);   /*for signal handlers*/

#if defined(SIG_IGN) && !defined(SIG_ERR)
#define SIG_ERR  ((Sigfunc*)-1)
#endif

#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))

char     *path_alloc(int *);
long     open_max(void);
void     clr_fl(int,int);
void     set_fl(int,int);
void     pr_exit(int);
void     pr_mask(const char *);
Sigfunc *signal_intr(int,Sigfunc *);

int     tty_cbreak(int);
int     tty_raw(int);
int     tty_reset(int);
int     tty_atexit(void);
#ifdef     ECHO        /*only if <termios.h> has been included*/
struct termios   *tty_termios(void);
#endif

void    sleep_us(unsigned int);
ssize_t readn(int,void*,size_t);
ssize_t writen(int,const void*,size_t);
void    daemonize(const char *);

int    s_pipe(int *);
int    recv_fd(int,ssize_t (*func)(int,const void*,size_t));
int    send_fd(int,int, ...);
int    send_err(int,int,const char*);
int    serv_listen(const char *);
int    serv_accept(int,uid_t*);
int    cli_conn(const char *);
int    buf_args(char *,int (*func)(int,char **));

int     ptym_open(char *,int);
int     ptys_open(char *);
#ifdef  TIOCGWINSZ
pid_t   pty_fork(int *,char *,int,const struct termios *,const struct winsize*);
#endif

int     lock_reg(int,int,int,off_t,int,off_t);
#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);
#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_dump(const char*, ...);
void    err_msg(const char *, ...);
void    err_quit(const char*, ...);
void    err_exit(int,const char*, ...);
void    err_ret(const char*,  ...);
void    err_sys(const  char*, ...);

void    log_msg(const char *, ...);
void    log_open(const char*,int,int);
void    log_quit(const char*, ...);
void    log_ret(const char *, ...);
void    log_sys(const char *, ...);

void    TELL_WAIT(void);
void    TELL_PARENT(pid_t);
void    TELL_CHILD(pid_t);
void    WAIT_PARENT(void);
void    WAIT_CHILD(void);

#endif