Revised autoreload interface
Make the header only contain the public interface and nothing from the implementation. All functions get a handle to their self object, like the img_ and tns_ and win_ functions. All necessary data (file path) is also passed as an argument, so that no extern redeclarations are needed. Make arl_setup_dir() private, it's not called outside the module. Make arl_handle() return true if the file has changed, so that the reloading of the file can be done by the caller.
This commit is contained in:
		
							
								
								
									
										18
									
								
								autoreload.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								autoreload.h
									
									
									
									
									
								
							@@ -21,23 +21,15 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "types.h"
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_cleanup(void);
 | 
					 | 
				
			||||||
void arl_handle(void);
 | 
					 | 
				
			||||||
void arl_init(void);
 | 
					 | 
				
			||||||
void arl_setup(void);
 | 
					 | 
				
			||||||
void arl_setup_dir(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	int wd;
 | 
						int wd;
 | 
				
			||||||
	bool watching_dir;
 | 
						bool watching_dir;
 | 
				
			||||||
} autoreload_t;
 | 
					} arl_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern autoreload_t autoreload;
 | 
					void arl_cleanup(arl_t*);
 | 
				
			||||||
extern int fileidx;
 | 
					bool arl_handle(arl_t*, const char*);
 | 
				
			||||||
extern fileinfo_t *files;
 | 
					void arl_init(arl_t*);
 | 
				
			||||||
 | 
					void arl_setup(arl_t*, const char*);
 | 
				
			||||||
void load_image(int);
 | 
					 | 
				
			||||||
void redraw(void);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* AUTORELOAD_H */
 | 
					#endif /* AUTORELOAD_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,35 +21,59 @@
 | 
				
			|||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <sys/inotify.h>
 | 
					#include <sys/inotify.h>
 | 
				
			||||||
#include <libgen.h>
 | 
					#include <libgen.h>
 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
#include "autoreload.h"
 | 
					#include "autoreload.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct timespec ten_ms = {0, 10000000};
 | 
					CLEANUP void arl_cleanup(arl_t *arl)
 | 
				
			||||||
 | 
					 | 
				
			||||||
void arl_cleanup(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (autoreload.fd != -1 && autoreload.wd != -1)
 | 
						if (arl->fd != -1 && arl->wd != -1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if(inotify_rm_watch(autoreload.fd, autoreload.wd))
 | 
							if(inotify_rm_watch(arl->fd, arl->wd))
 | 
				
			||||||
			error(0, 0, "Failed to remove inotify watch.");
 | 
								error(0, 0, "Failed to remove inotify watch.");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_handle(void)
 | 
					static void arl_setup_dir(arl_t *arl, const char *filepath)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						char *dntmp, *dn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (arl->fd == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							error(0, 0, "Uninitialized, could not add inotify watch on directory.");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* get dirname */
 | 
				
			||||||
 | 
						dntmp = (char*) strdup(filepath);
 | 
				
			||||||
 | 
						dn = (char*) dirname(dntmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* this is not one-shot as other stuff may be created too
 | 
				
			||||||
 | 
						   note: we won't handle deletion of the directory itself,
 | 
				
			||||||
 | 
						     this is a design decision								*/
 | 
				
			||||||
 | 
						arl->wd = inotify_add_watch(arl->fd, dn,IN_CREATE);
 | 
				
			||||||
 | 
						if (arl->wd == -1)
 | 
				
			||||||
 | 
							error(0, 0, "Failed to add inotify watch on directory '%s'.", dn);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							arl->watching_dir = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(dntmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool arl_handle(arl_t *arl, const char *filepath)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool reload = false;
 | 
				
			||||||
	ssize_t len;
 | 
						ssize_t len;
 | 
				
			||||||
	char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
 | 
						char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
 | 
				
			||||||
	const struct inotify_event *event;
 | 
						const struct inotify_event *event;
 | 
				
			||||||
	char *ptr;
 | 
						char *ptr;
 | 
				
			||||||
	char *fntmp, *fn;
 | 
						char *fntmp, *fn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	len = read(autoreload.fd, buf, sizeof buf);
 | 
						len = read(arl->fd, buf, sizeof buf);
 | 
				
			||||||
	if (len == -1)
 | 
						if (len == -1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		error(0, 0, "Failed to read inotify events.");
 | 
							error(0, 0, "Failed to read inotify events.");
 | 
				
			||||||
		return;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (ptr = buf; ptr < buf + len;
 | 
						for (ptr = buf; ptr < buf + len;
 | 
				
			||||||
@@ -61,17 +85,16 @@ void arl_handle(void)
 | 
				
			|||||||
		/* events from watching the file itself */
 | 
							/* events from watching the file itself */
 | 
				
			||||||
		if (event->mask & IN_CLOSE_WRITE)
 | 
							if (event->mask & IN_CLOSE_WRITE)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			load_image(fileidx);
 | 
								reload = true;
 | 
				
			||||||
			redraw();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (event->mask & IN_DELETE_SELF)
 | 
							if (event->mask & IN_DELETE_SELF)
 | 
				
			||||||
			arl_setup_dir();
 | 
								arl_setup_dir(arl, filepath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* events from watching the file's directory */
 | 
							/* events from watching the file's directory */
 | 
				
			||||||
		if (event->mask & IN_CREATE)
 | 
							if (event->mask & IN_CREATE)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			fntmp = strdup(files[fileidx].path);
 | 
								fntmp = strdup(filepath);
 | 
				
			||||||
			fn = basename(fntmp);
 | 
								fn = basename(fntmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (0 == strcmp(event->name, fn))
 | 
								if (0 == strcmp(event->name, fn))
 | 
				
			||||||
@@ -79,76 +102,49 @@ void arl_handle(void)
 | 
				
			|||||||
				/* this is the file we're looking for */
 | 
									/* this is the file we're looking for */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				/* cleanup, this has not been one-shot */
 | 
									/* cleanup, this has not been one-shot */
 | 
				
			||||||
				if (autoreload.watching_dir)
 | 
									if (arl->watching_dir)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					if(inotify_rm_watch(autoreload.fd, autoreload.wd))
 | 
										if(inotify_rm_watch(arl->fd, arl->wd))
 | 
				
			||||||
						error(0, 0, "Failed to remove inotify watch.");
 | 
											error(0, 0, "Failed to remove inotify watch.");
 | 
				
			||||||
					autoreload.watching_dir = false;
 | 
										arl->watching_dir = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				/* when too fast, imlib2 can't load the image */
 | 
									reload = true;
 | 
				
			||||||
				nanosleep(&ten_ms, NULL);
 | 
					 | 
				
			||||||
				load_image(fileidx);
 | 
					 | 
				
			||||||
				redraw();
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			free(fntmp);
 | 
								free(fntmp);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return reload;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_init(void)
 | 
					void arl_init(arl_t *arl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* this needs to be done only once */
 | 
						/* this needs to be done only once */
 | 
				
			||||||
	autoreload.fd = inotify_init();
 | 
						arl->fd = inotify_init();
 | 
				
			||||||
	autoreload.watching_dir = false;
 | 
						arl->watching_dir = false;
 | 
				
			||||||
	if (autoreload.fd == -1)
 | 
						if (arl->fd == -1)
 | 
				
			||||||
		error(0, 0, "Could not initialize inotify.");
 | 
							error(0, 0, "Could not initialize inotify.");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_setup(void)
 | 
					void arl_setup(arl_t *arl, const char *filepath)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (autoreload.fd == -1)
 | 
						if (arl->fd == -1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		error(0, 0, "Uninitialized, could not add inotify watch.");
 | 
							error(0, 0, "Uninitialized, could not add inotify watch.");
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* may have switched from a deleted to another image */
 | 
						/* may have switched from a deleted to another image */
 | 
				
			||||||
	if (autoreload.watching_dir)
 | 
						if (arl->watching_dir)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (inotify_rm_watch(autoreload.fd, autoreload.wd))
 | 
							if (inotify_rm_watch(arl->fd, arl->wd))
 | 
				
			||||||
			error(0, 0, "Failed to remove inotify watch.");
 | 
								error(0, 0, "Failed to remove inotify watch.");
 | 
				
			||||||
		autoreload.watching_dir = false;
 | 
							arl->watching_dir = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	autoreload.wd = inotify_add_watch(autoreload.fd, files[fileidx].path,
 | 
						arl->wd = inotify_add_watch(arl->fd, filepath,
 | 
				
			||||||
		IN_ONESHOT | IN_CLOSE_WRITE | IN_DELETE_SELF);
 | 
							IN_ONESHOT | IN_CLOSE_WRITE | IN_DELETE_SELF);
 | 
				
			||||||
	if (autoreload.wd == -1)
 | 
						if (arl->wd == -1)
 | 
				
			||||||
		error(0, 0, "Failed to add inotify watch on file '%s'.", files[fileidx].path);
 | 
							error(0, 0, "Failed to add inotify watch on file '%s'.", filepath);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_setup_dir(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char *dntmp, *dn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (autoreload.fd == -1)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		error(0, 0, "Uninitialized, could not add inotify watch on directory.");
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* get dirname */
 | 
					 | 
				
			||||||
	dntmp = (char*) strdup(files[fileidx].path);
 | 
					 | 
				
			||||||
	dn = (char*) dirname(dntmp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* this is not one-shot as other stuff may be created too
 | 
					 | 
				
			||||||
	   note: we won't handle deletion of the directory itself,
 | 
					 | 
				
			||||||
	     this is a design decision								*/
 | 
					 | 
				
			||||||
	autoreload.wd = inotify_add_watch(autoreload.fd, dn,IN_CREATE);
 | 
					 | 
				
			||||||
	if (autoreload.wd == -1)
 | 
					 | 
				
			||||||
		error(0, 0, "Failed to add inotify watch on directory '%s'.", dn);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		autoreload.watching_dir = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(dntmp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,14 +18,26 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "autoreload.h"
 | 
					#include "autoreload.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_cleanup(void) { }
 | 
					void arl_cleanup(arl_t *arl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						(void) arl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_handle(void) { }
 | 
					bool arl_handle(arl_t *arl, const char *filepath)
 | 
				
			||||||
 | 
					{ 
 | 
				
			||||||
 | 
						(void) arl;
 | 
				
			||||||
 | 
						(void) filepath;
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arl_init(void) { }
 | 
					void arl_init(arl_t *arl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
void arl_setup(void) { }
 | 
						(void) arl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
void arl_setup_dir(void) { }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void arl_setup(arl_t *arl, const char *filepath)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						(void) arl;
 | 
				
			||||||
 | 
						(void) filepath;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								main.c
									
									
									
									
									
								
							@@ -28,6 +28,7 @@
 | 
				
			|||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <sys/time.h>
 | 
					#include <sys/time.h>
 | 
				
			||||||
#include <sys/wait.h>
 | 
					#include <sys/wait.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
#include <X11/keysym.h>
 | 
					#include <X11/keysym.h>
 | 
				
			||||||
#include <X11/XF86keysym.h>
 | 
					#include <X11/XF86keysym.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,6 +58,7 @@ void slideshow(void);
 | 
				
			|||||||
void clear_resize(void);
 | 
					void clear_resize(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
appmode_t mode;
 | 
					appmode_t mode;
 | 
				
			||||||
 | 
					arl_t arl;
 | 
				
			||||||
img_t img;
 | 
					img_t img;
 | 
				
			||||||
tns_t tns;
 | 
					tns_t tns;
 | 
				
			||||||
win_t win;
 | 
					win_t win;
 | 
				
			||||||
@@ -65,7 +67,6 @@ fileinfo_t *files;
 | 
				
			|||||||
int filecnt, fileidx;
 | 
					int filecnt, fileidx;
 | 
				
			||||||
int alternate;
 | 
					int alternate;
 | 
				
			||||||
int markcnt;
 | 
					int markcnt;
 | 
				
			||||||
autoreload_t autoreload;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int prefix;
 | 
					int prefix;
 | 
				
			||||||
bool extprefix;
 | 
					bool extprefix;
 | 
				
			||||||
@@ -100,7 +101,7 @@ timeout_t timeouts[] = {
 | 
				
			|||||||
void cleanup(void)
 | 
					void cleanup(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	img_close(&img, false);
 | 
						img_close(&img, false);
 | 
				
			||||||
	arl_cleanup();
 | 
						arl_cleanup(&arl);
 | 
				
			||||||
	tns_free(&tns);
 | 
						tns_free(&tns);
 | 
				
			||||||
	win_close(&win);
 | 
						win_close(&win);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -320,7 +321,7 @@ void load_image(int new)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	info.open = false;
 | 
						info.open = false;
 | 
				
			||||||
	open_info();
 | 
						open_info();
 | 
				
			||||||
	arl_setup();
 | 
						arl_setup(&arl, files[fileidx].path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (img.multi.cnt > 0 && img.multi.animate)
 | 
						if (img.multi.cnt > 0 && img.multi.animate)
 | 
				
			||||||
		set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
 | 
							set_timeout(animate, img.multi.frames[img.multi.sel].delay, true);
 | 
				
			||||||
@@ -676,6 +677,8 @@ void on_buttonpress(XButtonEvent *bev)
 | 
				
			|||||||
	prefix = 0;
 | 
						prefix = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct timespec ten_ms = {0, 10000000};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void run(void)
 | 
					void run(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int xfd;
 | 
						int xfd;
 | 
				
			||||||
@@ -689,8 +692,8 @@ void run(void)
 | 
				
			|||||||
		init_thumb = mode == MODE_THUMB && tns.initnext < filecnt;
 | 
							init_thumb = mode == MODE_THUMB && tns.initnext < filecnt;
 | 
				
			||||||
		load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end;
 | 
							load_thumb = mode == MODE_THUMB && tns.loadnext < tns.end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((init_thumb || load_thumb || to_set || info.fd != -1 || autoreload.fd != -1) &&
 | 
							if ((init_thumb || load_thumb || to_set || info.fd != -1 ||
 | 
				
			||||||
		    XPending(win.env.dpy) == 0)
 | 
								   arl.fd != -1) && XPending(win.env.dpy) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (load_thumb) {
 | 
								if (load_thumb) {
 | 
				
			||||||
				set_timeout(redraw, TO_REDRAW_THUMBS, false);
 | 
									set_timeout(redraw, TO_REDRAW_THUMBS, false);
 | 
				
			||||||
@@ -712,15 +715,21 @@ void run(void)
 | 
				
			|||||||
					FD_SET(info.fd, &fds);
 | 
										FD_SET(info.fd, &fds);
 | 
				
			||||||
					xfd = MAX(xfd, info.fd);
 | 
										xfd = MAX(xfd, info.fd);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (autoreload.fd != -1) {
 | 
									if (arl.fd != -1) {
 | 
				
			||||||
					FD_SET(autoreload.fd, &fds);
 | 
										FD_SET(arl.fd, &fds);
 | 
				
			||||||
					xfd = MAX(xfd, autoreload.fd);
 | 
										xfd = MAX(xfd, arl.fd);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				select(xfd + 1, &fds, 0, 0, to_set ? &timeout : NULL);
 | 
									select(xfd + 1, &fds, 0, 0, to_set ? &timeout : NULL);
 | 
				
			||||||
				if (info.fd != -1 && FD_ISSET(info.fd, &fds))
 | 
									if (info.fd != -1 && FD_ISSET(info.fd, &fds))
 | 
				
			||||||
					read_info();
 | 
										read_info();
 | 
				
			||||||
				if (autoreload.fd != -1 && FD_ISSET(autoreload.fd, &fds))
 | 
									if (arl.fd != -1 && FD_ISSET(arl.fd, &fds)) {
 | 
				
			||||||
					arl_handle();
 | 
										if (arl_handle(&arl, files[fileidx].path)) {
 | 
				
			||||||
 | 
											/* when too fast, imlib2 can't load the image */
 | 
				
			||||||
 | 
											nanosleep(&ten_ms, NULL);
 | 
				
			||||||
 | 
											load_image(fileidx);
 | 
				
			||||||
 | 
											redraw();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -864,7 +873,7 @@ int main(int argc, char **argv)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	win_init(&win);
 | 
						win_init(&win);
 | 
				
			||||||
	img_init(&img, &win);
 | 
						img_init(&img, &win);
 | 
				
			||||||
	arl_init();
 | 
						arl_init(&arl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((homedir = getenv("XDG_CONFIG_HOME")) == NULL || homedir[0] == '\0') {
 | 
						if ((homedir = getenv("XDG_CONFIG_HOME")) == NULL || homedir[0] == '\0') {
 | 
				
			||||||
		homedir = getenv("HOME");
 | 
							homedir = getenv("HOME");
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user