#!mkcmd
# $Id: sbp.m,v 2.10 2012/09/28 14:29:38 ksb Exp $
# command line interface for sync-backup-partitions			(ksb)
from '<sys/types.h>'
from '<sys/stat.h>'
from '<stdlib.h>'
from '<sysexits.h>'

from '"machine.h"'
from '"read.h"'
from '"sbp.h"'
from '"dicer.h"'

require "std_help.m" "std_version.m" "std_control.m"
require "sbp.mi" "sbp.mh"
require "util_mountpt.m"
require "sbp-platform.m"

basename "sbp" ""
basename "sync-backup-partitions" ""

%i
static char rcsid[] =
	"$Id: sbp.m,v 2.10 2012/09/28 14:29:38 ksb Exp $";

static SBP_ENTRY *pBPBackups;
static char acDefSnap[] = "raw,unlink,backing-store=/tmp/sfs$$";
int iExitCode = 0;
%%
%h
extern int iExitCode;
%%

augment key "PATH" 1 init {
	"/usr/local/bin" "/usr/local/etc"
	"/etc" "/usr/sbin" "/usr/lib/fs/ufs" "/sbin" "/usr/etc" "/stand"
	"/usr/bin" "/bin"
}
key "sbp_dump" 1 init {
	"ufsdump" "dump" "backup" "rdump"
}
key "sbp_restore" 1 init {
	"ufsrestore" "restore" "rrestore"
}
key "sbp_install" 1 init {
	"install"
}
key "sbp_fstab" 1 init {
	"fstab" "vfstab" "checklist" "filesystems"
}
key "sbp_fssnap" 1 init {
	"fssnap" "false"
}
key "sbp_mk" 1 init {
	"mk" "dwim"
}

augment action 'V' {
	user 'Version();'
}

boolean 'a' {
	named "fAsync"
	help "mount the destination file systems async to speed the backup"
}
boolean 'i' {
	hidden
	named "fInteract"
	help "be interactive at each major step"
}
boolean 'J' {
	hidden named "fInsane"
	help "debug inode guess code"
}
boolean 'j' {
	named "fJudge"
	help "just guess at the newfs tune for backup partitions"
}
boolean 'K' {
	named "fCheckSource"
	init "1"
	help "do not check the status of the source filesystems"
}
char* 'f' {
	named "pcFstab"
	init "acFstabPath"
	param "fstab"
	help "the file system table to read"
}
boolean 'F' {
	named "fUpdateFstab"
	init "1"
	help "supress the update of the backup file system table"
}

char* 'm' {
	named "pcMtPoint"
	init '"/backup"'
	param "backup"
	user "CheckPoint(%n);"
	help "construct the backup partition on this mount-point"
}
char* 'r' {
	named "pcMtRoot"
	init '"/"'
	param "source"
	help "the data source heirarchy"
}
char* 'L' {
	hidden named "pcLabel"
	param "label"
	help "execute before sync to label the backup disk"
}
char* 'X' {
	hidden name "pcXapply"
	param "xbefore"
	help "execute across all pairs before we start any backups"
}
char* 'B' {
	hidden named "pcBefore"
	param "before"
	help "execute before each filesystem is sync'd"
}
char* 'C' {
	named "pcCleanup"
	param "cmd"
	help "cleanup command executed after copy, before umount"
}
char* 'A' {
	hidden named "pcAfter"
	param "after"
	help "execute after each filesystem is sync'd"
}
char* 'H' {
	named "pcHow"
	init '"dump"'
	param "how"
	once user "SetHow(%n);"
	help "specify how to sync the partitions (use ? for help)"
}
accum [","] 'o' {
	named "pcFsSnapOpts"
	param "fssnap-options"
	after 'if ((char *)0 == %n && 0 == strcmp(%rHn, "fssnap")) {%n = acDefSnap;}'
	help "options to pass to fssnap mount"
}
double 'D' {
	hidden named "dBlockFull" init "90.0"
	help "the percent of data we expect to use on the file system"
}
double 'I' {
	hidden named "dFileFull" init "60.0"
	help "the percent of inode that should be used when we are at capacity"
}
char* 'M' {
	named "pcMkNewfs" init "(char *)0"
	param "marker"
	help "use an mk(1L) marked line to build new filesystems"
}
char* 'E' {
	named "pcMkRule" init '"%Q -DFS_CLUE=\'%i\' -m%M -d\'%r\' -t\'%T\' -l\'0\' %f"'
	param "rule"
	help "expand a different shell rule to invocation mk"
}
char* 'T' {
	named "pcUserDb" init '(char *)0'
	param "template"
	help "provide a custom mk rule-set, rather than the default"
}

after {
	named "ReadFs"
	update "pBPBackups = %n(pcFstab);"
}

list {
	named "DoSync"
	param "file-systems"
	update "%n(%#, %@, pBPBackups);"
	help "list of partitions to sync"
}

exit {
	named "exit" from '<stdlib.h>'
	update "exit(iExitCode);"
	help ""
}

%c
/* explain what we found						(ksb)
 */
static void
Version()
{
	printf("%s:  %s\n", progname, DicerVersion);
	printf("%s: backup mount point: %s\n", progname, pcMtPoint);
	printf("%s: list: %s\n", progname, acFstabPath);
	printf("%s: install: %s\n", progname, acInstallPath);
	printf("%s: dump: %s [%%D]\n", progname, acDumpPath);
	printf("%s: restore: %s [%%R]\n", progname, acRestorePath);
	printf("%s: mk: %s [%%Q]\n", progname, acMkPath);
	printf("%s: mk command: %s\n", progname, pcMkRule);
#if HAVE_FSSNAP
	printf("%s: fssnap: %s -o %s [%%S]\n", progname, acFsSnap, acDefSnap);
#endif
	/* MethHelp(stdout); */
}

/* a strong spell like this must have some safe-guards			(ksb)
 * the proposed backup mount-point must
 *	start with a slash
 *	not be "/", "/usr", "/opt", "/var" (or /export, /home I guess)
 */
static void
CheckPoint(pcParam)
char *pcParam;
{
	if ('/' != pcParam[0]) {
		fprintf(stderr, "%s: backup mount point \"%s\" must start with a slash\n", progname, pcParam);
		exit(EX_DATAERR);
	}
	switch (pcParam[1]) {
	case '\000':
		break;
	case 'e':
		if (0 == strcmp("/export", pcParam)) {
			break;
		}
		return;
	case 'h':
		if (0 == strcmp("/home", pcParam)) {
			break;
		}
		return;
	case 'u':
		if (0 == strcmp("/usr", pcParam)) {
			break;
		}
		if (0 == strcmp("/usr/local", pcParam)) {
			break;
		}
		return;
	case 'v':
		if (0 == strcmp("/var", pcParam)) {
			break;
		}
		return;
	case 'o':
		if (0 == strcmp("/opt", pcParam)) {
			break;
		}
	default:
		return;
	}
	fprintf(stderr, "%s: a backup mount of \"%s\" would destroy the system\n", progname, pcParam);
	exit(EX_NOPERM);
}
%%
