shithub: fingerd

ref: 93c347adf541f8588aa610f66040dd96d39ccc3e
dir: /fingerd.c/

View raw version
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <bio.h>

#define BUFSIZ 8192

char *LOG = "fingerd";
char *nsfile = "/lib/namespace.finger";
char *usernotfound = "/lib/finger/usernotfound";
char *filenotfound = "/lib/finger/filenotfound";
char *motd = "/lib/finger/motd";

int puserlist = 1;

int
vaccess(char *file)
{
	int fd;
	fd = open(file, OREAD);
	if (fd < 0){
		return 0;
	}
	close(fd);
	return 1;
}

void
strrepl(char *str, char f, char t)
{
	while (*str != 0){
		if (*str == f)
			*str = t;
		str++;
	}
}

int
cat(char *file, int perr)
{
	int n, fd;
	char buf[BUFSIZ];
	fd = open(file, OREAD);
	if (fd < 0){
		if (perr)
			print("File %s not Found.\r\n", file);
		return 0;
	}
	while ((n = read(fd, buf, BUFSIZ)) > 0)
		if (write(1, buf, n) != n)
			print("Error writing data!\r\n");
	close(fd);
	return 1;
}

char*
splitpath(char *req)
{
	char *file;
	file = strchr(req, '+');
	if (file == nil || strlen(file) <= 1)
		return "finger";
	file[0] = 0;
	strrepl(file+1, '+', '/');
	return file+1;
}

void
printuserinfo(char *user)
{
	print("%s\r\n", user);
}

void
printuserlist(void)
{
	Dir *dirbuf;
	char *path;
	int fd, n, i;
	fd = open("/usr", OREAD);
	if (fd < 0){
		print("Can't list users.\r\n");
		return;
	}
	n = dirreadall(fd, &dirbuf);
	close(fd);
	if (n)
		print("User list:\r\n");
	else
		print("No users.\r\n");
	for (i = 0; i < n; i++){
		path = smprint("/usr/%s/finger/finger", dirbuf[i].name);
		if (vaccess(path)){
			free(path);
			printuserinfo(dirbuf[i].name);
		}
	}
}

void
printnouser(char *user)
{
	if (!cat(usernotfound, 0))
		print("User '%s' not found or private.\r\n", user);
}

void
printnofile(char *file)
{
	if (!cat(filenotfound, 0))
		print("File '%s' not found.\r\n", file);
	syslog(1, LOG, "file %s not found", file);
}

void
printglobalfile(char *file)
{
	if (bind("/lib/finger/tree/", "/", MREPL) < 0) {
		print("unable to bind.\r\n");
		syslog(1, LOG, "unable to bind /lib/finger/tree: %r");
		return;
	}
	chdir("/");
	if (!vaccess(file)){
		printnofile(file);
		return;
	}
	if (!cat(file, OREAD))
		printnofile(file);
}

void
printuserfile(char *user, char *file)
{
	char *path;
	
	path = smprint("/usr/%s/finger/", user);
	if (bind(path, "/", MREPL) < 0) {
		print("unable to bind!\r\n");
		syslog(1, LOG, "unable to bind /usr/%s/finger: %r", user);
		free(path);
		return;
	}
	free(path);
	chdir("/");
	if (!vaccess("finger")){
		printnouser(user);
		return;
	}
	if (!cat(file, OREAD))
		printnofile(file);
}

void
main(int argc, char **argv)
{
	int n;
	Biobuf *bin;
	char *user, *file, *req;

	ARGBEGIN{
	case 'l':
		puserlist = 0;
		break;
	} ARGEND

	bin = Bfdopen(0, OREAD);
	req = Brdline(bin, '\n');
	if (req == nil){
		syslog(1, LOG, "bad read: %r");
		sysfatal("bad read: %r");
	}
	n = Blinelen(bin);
	req[n-1] = 0;
	n--;
	if (req[n-1] == '\r'){
		req[n-1] = 0;
		n--;
	}
	
	rfork(RFNAMEG|RFNOMNT);

	if (vaccess(nsfile)){
		if (addns("none", nsfile) < 0){
			print("internal error.\r\n");
			syslog(1, LOG, "addns failed: %r");
			sysfatal("addns failed: %r");
		}
	}

	switch(n){
	case 0:  /* null server request */
		if (!cat(motd, 0))
			print("motd not found.\r\n");
		if (puserlist)
			printuserlist();
		break;
	default: /* non-null request */
		file = splitpath(req);
		user = req;
		if (strlen(user) <= 0) {
			printglobalfile(file);
			break;
		}
		printuserfile(user, file);
	}
	exits(nil);
}