/*
 * Name: unshlight.c
 * Description: Unmount the given volume mounted by shlight
 * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
 * Date: 1997-08-18
 * Copyright: GNU-GPL
 * Tabsize: 4
 */

#include "syshdr.h"
#include <mntent.h>
#include "my_defines.h"

/* ------------------------------------------------------------------------- */

static char	*my_name;

/* ------------------------------------------------------------------------- */

static int	umount_dir(char *path)
{
FILE			*fpin;
struct mntent	*ent;
int				i, pid, rval = 0, found_any = 0;
char			resolvedPath[MAXPATHLEN];

	if((fpin = setmntent(MOUNTED, "r")) == NULL){
		fprintf(stderr, "%s: cannot open mtab file ->%s<-: %s\n",
										my_name, MOUNTED, strerror(errno));
		return -1;
	}else{
		if(path != NULL){
			if(realpath(path, resolvedPath) == NULL){
				fprintf(stderr, "%s: error resolving path ->%s<-: %s\n",
											my_name, path, strerror(errno));
				return -1;
			}
		}
		while((ent = getmntent(fpin)) != NULL){
			if(path == NULL || strcmp(ent->mnt_dir, resolvedPath) == 0){
				found_any = 1;
				if(sscanf(ent->mnt_fsname, "shlight-%d", &pid) == 1){
					if(unmount(ent->mnt_dir) == 0){
						if(kill(pid, 1) != 0){
							fprintf(stderr, "%s: can\'t signal pid %d: %s\n",
												my_name, pid, strerror(errno));
						}else{
							for(i=0;kill(pid, 0) == 0 && i < 20;i++){
								usleep(100000);
							}
							if(i >= 20){
								fprintf(stderr,"%s: shlight pid %d won\'t die\n",
																my_name, pid);
							}
						}
					}else{
						fprintf(stderr, "%s: error unmounting ->%s<-: %s\n",
									my_name, ent->mnt_dir, strerror(errno));
					}
				}else if(path != NULL){
					fprintf(stderr, "%s: type ->%s<- not mounted by shlight\n",
													my_name, ent->mnt_dir);
					rval = -1;
				}
			}
		}
		endmntent(fpin);
		if(!found_any && path != NULL){
			fprintf(stderr, "%s: directory ->%s<- not found in mtab\n",
													my_name, resolvedPath);
		}
	}
	return rval;
}

/* ------------------------------------------------------------------------- */

static void	print_all(void)
{
FILE			*fpin;
struct mntent	*ent;
int				pid;

	if((fpin = setmntent(MOUNTED, "r")) == NULL){
		fprintf(stderr, "%s: cannot open mtab file ->%s<-: %s\n",
										my_name, MOUNTED, strerror(errno));
		return;
	}else{
		while((ent = getmntent(fpin)) != NULL){
			if(sscanf(ent->mnt_fsname, "shlight-%d", &pid) == 1){
				printf("%s\n", ent->mnt_dir);
			}
		}
		endmntent(fpin);
	}
}

/* ------------------------------------------------------------------------- */

static void	print_usage(void)
{
	fprintf(stderr, "usage: (%s (-l | -a)) | (%s <mountpoint>+)\n",
													my_name, my_name);
}

/* ------------------------------------------------------------------------- */

int	main(int argc, char **argv)
{
int		i, error = 0, rval;

	my_name = argv[0];
	if(argc == 1){
		print_usage();
	}else if(argc == 2){
		if(strcmp(argv[1], "-l") == 0){
			printf("List of shlight mounted directories:\n");
			print_all();
		}else if(strcmp(argv[1], "-a") == 0){
			umount_dir(NULL);
		}else{
			error |= umount_dir(argv[1]);
		}
	}else{
		for(i=1;i<argc;i++){
			error |= umount_dir(argv[i]);
		}
	}
	rval = error ? 1 : 0;
	return rval;
}

/* ------------------------------------------------------------------------- */
