summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in29
-rw-r--r--source3/configure.in3
-rw-r--r--source3/include/localedir.h6
-rwxr-xr-xsource3/locale/pam_winbind/genmsg25
-rw-r--r--source3/localedir.c3
-rw-r--r--source3/m4/check_path.m419
-rw-r--r--source3/nsswitch/pam_winbind.c117
-rw-r--r--source3/nsswitch/pam_winbind.h15
-rw-r--r--source3/script/installmo.sh83
-rw-r--r--source3/script/uninstallmo.sh1
10 files changed, 244 insertions, 57 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 6e40ba404a..4a0590c8ed 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -140,6 +140,9 @@ PRIVATE_DIR = $(PRIVATEDIR)
# This is where SWAT images and help files go
SWATDIR = @swatdir@
+# This is where locale(mo) files go
+LOCALEDIR= @localedir@
+
# the directory where lock files go
LOCKDIR = @lockdir@
@@ -173,7 +176,8 @@ PATH_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" \
-DCONFIGDIR=\"$(CONFIGDIR)\" \
-DCODEPAGEDIR=\"$(CODEPAGEDIR)\" \
-DCACHEDIR=\"$(CACHEDIR)\" \
- -DSTATEDIR=\"$(STATEDIR)\"
+ -DSTATEDIR=\"$(STATEDIR)\" \
+ -DLOCALEDIR=\"$(LOCALEDIR)\"
# Note that all executable programs now provide for an optional executable suffix.
@@ -803,7 +807,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
$(LIBADS_OBJ) $(POPT_LIB_OBJ) \
$(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(LDB_OBJ)
-PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \
+PAM_WINBIND_OBJ = nsswitch/pam_winbind.o localedir.o $(WBCOMMON_OBJ) \
$(LIBREPLACE_OBJ) @BUILD_INIPARSER@
LIBSMBCLIENT_OBJ0 = \
@@ -1312,6 +1316,13 @@ dynconfig.o: dynconfig.c Makefile
echo "$(COMPILE_CC_PATH)" 1>&2;\
$(COMPILE_CC_PATH) >/dev/null 2>&1
+localedir.o: localedir.c Makefile
+ @echo Compiling $*.c
+ @$(COMPILE_CC_PATH) && exit 0;\
+ echo "The following command failed:" 1>&2;\
+ echo "$(COMPILE_CC_PATH)" 1>&2;\
+ $(COMPILE_CC_PATH) >/dev/null 2>&1
+
lib/pidfile.o: lib/pidfile.c
@echo Compiling $*.c
@$(COMPILE_CC_PATH) && exit 0;\
@@ -2558,7 +2569,7 @@ bin/test_lp_load@EXEEXT@: $(BINARY_PREREQS) $(TEST_LP_LOAD_OBJ) @BUILD_POPT@ @LI
install:: installservers installbin @INSTALL_CIFSMOUNT@ @INSTALL_CIFSUPCALL@ installman \
installscripts installdat installmodules @SWAT_INSTALL_TARGETS@ \
- @INSTALL_PAM_MODULES@ installlibs
+ @INSTALL_PAM_MODULES@ installlibs installmo
install-everything:: install installmodules
@@ -2571,7 +2582,7 @@ install-everything:: install installmodules
# is not used
installdirs::
- @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR)
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR) $(CODEPAGEDIR) $(MODULESDIR) $(LOCALEDIR)
installservers:: all installdirs
@$(SHELL) script/installbin.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(SBINDIR) $(SBIN_PROGS)
@@ -2637,6 +2648,9 @@ revert::
installman:: installdirs
@$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
+installmo:: all installdirs
+ @$(SHELL) $(srcdir)/script/installmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
+
.PHONY: showlayout
showlayout::
@@ -2656,7 +2670,10 @@ showlayout::
@echo " codepagedir: $(CODEPAGEDIR)"
-uninstall:: uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
+uninstall:: uninstallmo uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ @UNINSTALL_CIFSUPCALL@ uninstallscripts uninstalldat uninstallswat uninstallmodules uninstalllibs @UNINSTALL_PAM_MODULES@
+
+uninstallmo::
+ @$(SHELL) $(srcdir)/script/uninstallmo.sh $(DESTDIR) $(LOCALEDIR) $(srcdir)
uninstallman::
@$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) C
@@ -2701,7 +2718,7 @@ uninstallpammodules::
done
# Toplevel clean files
-TOPFILES=dynconfig.o
+TOPFILES=dynconfig.o localedir.o
cleanlibs::
-rm -f ../lib/*/*.o ../lib/*/*/*.o \
diff --git a/source3/configure.in b/source3/configure.in
index 24341e0bec..1adb56ad91 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -654,7 +654,7 @@ AUTH_LIBS="${AUTH_LIBS} ${CRYPT_LIBS}"
AC_CHECK_HEADERS(aio.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h)
AC_CHECK_HEADERS(unistd.h grp.h sys/id.h memory.h alloca.h)
-AC_CHECK_HEADERS(limits.h float.h pthread.h)
+AC_CHECK_HEADERS(limits.h float.h pthread.h libintl.h)
AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h)
@@ -1029,6 +1029,7 @@ AC_CHECK_FUNCS(memalign posix_memalign hstrerror)
AC_CHECK_HEADERS(sys/mman.h)
# setbuffer, shmget, shm_open are needed for smbtorture
AC_CHECK_FUNCS(shmget shm_open)
+AC_CHECK_FUNCS(gettext dgettext)
# Find a method of generating a stack trace
AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
diff --git a/source3/include/localedir.h b/source3/include/localedir.h
new file mode 100644
index 0000000000..2a291d3ceb
--- /dev/null
+++ b/source3/include/localedir.h
@@ -0,0 +1,6 @@
+#ifndef __LOCALEDIR_H__
+#define __LOCALEDIR_H__
+
+extern const char *dyn_LOCALEDIR;
+
+#endif
diff --git a/source3/locale/pam_winbind/genmsg b/source3/locale/pam_winbind/genmsg
new file mode 100755
index 0000000000..5aa258aa85
--- /dev/null
+++ b/source3/locale/pam_winbind/genmsg
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+FILES="../../nsswitch/pam_winbind.c ../../nsswitch/pam_winbind.h"
+LANGS="af ar bg bn bs ca cs cy da de el en_GB en_US es et fi fr gl gu he hi hr hu id it ja ka km ko lo lt mk mr nb nl pa pl pt_BR pt ro ru si sk sl sr sv ta th tr uk vi wa xh zh_CN zh_TW zu"
+
+XGETTEXT=xgettext
+MSGMERGE=msgmerge
+
+WIDTH=256
+
+$XGETTEXT --default-domain="pam_winbind" \
+ --add-comments \
+ --keyword=_ --keyword=N_ \
+ --width=${WIDTH} \
+ ${FILES}
+
+for lang in ${LANGS}; do
+ echo -n $lang
+ touch ${lang}.po
+ mv ${lang}.po ${lang}.po.old
+ ${MSGMERGE} --width=${WIDTH} ${lang}.po.old pam_winbind.po -o ${lang}.po
+ rm -fr ${lang}.po.old
+done
+
+rm -fr pam_winbind.po
diff --git a/source3/localedir.c b/source3/localedir.c
new file mode 100644
index 0000000000..20f69219ed
--- /dev/null
+++ b/source3/localedir.c
@@ -0,0 +1,3 @@
+#include "localedir.h"
+
+const char *dyn_LOCALEDIR = LOCALEDIR;
diff --git a/source3/m4/check_path.m4 b/source3/m4/check_path.m4
index 0cff397c93..da6c922233 100644
--- a/source3/m4/check_path.m4
+++ b/source3/m4/check_path.m4
@@ -30,6 +30,7 @@ swatdir="\${prefix}/swat"
codepagedir="\${MODULESDIR}"
statedir="\${LOCKDIR}"
cachedir="\${LOCKDIR}"
+localedir="\${prefix}/share/locale"
AC_ARG_WITH(fhs,
[AS_HELP_STRING([--with-fhs],[Use FHS-compliant paths (default=no)])],
@@ -242,6 +243,23 @@ AC_ARG_WITH(mandir,
;;
esac])
+################################################
+# set locale directory location
+AC_ARG_WITH(localedir,
+[ --with-localedir=DIR Where to put po files ($ac_default_prefix/share/locale)],
+[ case "$withval" in
+ yes|no)
+ #
+ # Just in case anybody does it
+ #
+ AC_MSG_WARN([--with-localedir called without argument - will use default])
+ ;;
+ *)
+ localedir="$withval"
+ ;;
+ esac])
+
+
AC_SUBST(configdir)
AC_SUBST(lockdir)
AC_SUBST(piddir)
@@ -258,6 +276,7 @@ AC_SUBST(cachedir)
AC_SUBST(rootsbindir)
AC_SUBST(pammodulesdir)
AC_SUBST(modulesdir)
+AC_SUBST(localedir)
#################################################
# set prefix for 'make test'
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
index 0c861e9f97..2c46a0c839 100644
--- a/source3/nsswitch/pam_winbind.c
+++ b/source3/nsswitch/pam_winbind.c
@@ -147,6 +147,21 @@ static const char *_pam_error_code_str(int err)
#define MAX_PASSWD_TRIES 3
+#ifdef HAVE_GETTEXT
+static char initialized = 0;
+
+static inline void textdomain_init(void);
+static inline void textdomain_init(void)
+{
+ if (!initialized) {
+ bindtextdomain(MODULE_NAME, dyn_LOCALEDIR);
+ initialized = 1;
+ }
+ return;
+}
+#endif
+
+
/*
* Work around the pam API that has functions with void ** as parameters
* These lead to strict aliasing warnings with gcc.
@@ -515,6 +530,10 @@ static int _pam_winbind_init_context(pam_handle_t *pamh,
{
struct pwb_context *r = NULL;
+#ifdef HAVE_GETTEXT
+ textdomain_init();
+#endif
+
r = TALLOC_ZERO_P(NULL, struct pwb_context);
if (!r) {
return PAM_BUF_ERR;
@@ -557,44 +576,44 @@ static const struct ntstatus_errors {
const char *error_string;
} ntstatus_errors[] = {
{"NT_STATUS_OK",
- "Success"},
+ N_("Success")},
{"NT_STATUS_BACKUP_CONTROLLER",
- "No primary Domain Controler available"},
+ N_("No primary Domain Controler available")},
{"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
- "No domain controllers found"},
+ N_("No domain controllers found")},
{"NT_STATUS_NO_LOGON_SERVERS",
- "No logon servers"},
+ N_("No logon servers")},
{"NT_STATUS_PWD_TOO_SHORT",
- "Password too short"},
+ N_("Password too short")},
{"NT_STATUS_PWD_TOO_RECENT",
- "The password of this user is too recent to change"},
+ N_("The password of this user is too recent to change")},
{"NT_STATUS_PWD_HISTORY_CONFLICT",
- "Password is already in password history"},
+ N_("Password is already in password history")},
{"NT_STATUS_PASSWORD_EXPIRED",
- "Your password has expired"},
+ N_("Your password has expired")},
{"NT_STATUS_PASSWORD_MUST_CHANGE",
- "You need to change your password now"},
+ N_("You need to change your password now")},
{"NT_STATUS_INVALID_WORKSTATION",
- "You are not allowed to logon from this workstation"},
+ N_("You are not allowed to logon from this workstation")},
{"NT_STATUS_INVALID_LOGON_HOURS",
- "You are not allowed to logon at this time"},
+ N_("You are not allowed to logon at this time")},
{"NT_STATUS_ACCOUNT_EXPIRED",
"Your account has expired. "
- "Please contact your System administrator"}, /* SCNR */
+ N_("Please contact your System administrator")}, /* SCNR */
{"NT_STATUS_ACCOUNT_DISABLED",
"Your account is disabled. "
- "Please contact your System administrator"}, /* SCNR */
+ N_("Please contact your System administrator")}, /* SCNR */
{"NT_STATUS_ACCOUNT_LOCKED_OUT",
"Your account has been locked. "
- "Please contact your System administrator"}, /* SCNR */
+ N_("Please contact your System administrator")}, /* SCNR */
{"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
- "Invalid Trust Account"},
+ N_("Invalid Trust Account")},
{"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
- "Invalid Trust Account"},
+ N_("Invalid Trust Account")},
{"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
- "Invalid Trust Account"},
+ N_("Invalid Trust Account")},
{"NT_STATUS_ACCESS_DENIED",
- "Access is denied"},
+ N_("Access is denied")},
{NULL, NULL}
};
@@ -604,7 +623,7 @@ static const char *_get_ntstatus_error_string(const char *nt_status_string)
for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) {
if (!strcasecmp(ntstatus_errors[i].ntstatus_string,
nt_status_string)) {
- return ntstatus_errors[i].error_string;
+ return _(ntstatus_errors[i].error_string);
}
}
return NULL;
@@ -832,14 +851,14 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
if (days == 0) {
_make_remark(ctx, PAM_TEXT_INFO,
- "Your password expires today");
+ _("Your password expires today"));
return true;
}
if (days > 0 && days < warn_pwd_expire) {
_make_remark_format(ctx, PAM_TEXT_INFO,
- "Your password will expire in %d %s",
- days, (days > 1) ? "days":"day");
+ _("Your password will expire in %d %s"),
+ days, (days > 1) ? _("days"):_("day"));
return true;
}
@@ -1231,9 +1250,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
if (PAM_WB_GRACE_LOGON(info3_user_flgs)) {
_make_remark(ctx, PAM_ERROR_MSG,
- "Grace login. "
- "Please change your password as soon you're "
- "online again");
+ _("Grace login. "
+ "Please change your password as soon you're "
+ "online again"));
_pam_log_debug(ctx, LOG_DEBUG,
"User %s logged on using grace logon\n",
username);
@@ -1241,9 +1260,9 @@ static void _pam_warn_logon_type(struct pwb_context *ctx,
} else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) {
_make_remark(ctx, PAM_ERROR_MSG,
- "Domain Controller unreachable, "
- "using cached credentials instead. "
- "Network resources may be unavailable");
+ _("Domain Controller unreachable, "
+ "using cached credentials instead. "
+ "Network resources may be unavailable"));
_pam_log_debug(ctx, LOG_DEBUG,
"User %s logged on using cached credentials\n",
username);
@@ -1266,10 +1285,10 @@ static void _pam_warn_krb5_failure(struct pwb_context *ctx,
{
if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) {
_make_remark(ctx, PAM_ERROR_MSG,
- "Failed to establish your Kerberos Ticket cache "
- "due time differences\n"
- "with the domain controller. "
- "Please verify the system time.\n");
+ _("Failed to establish your Kerberos Ticket cache "
+ "due time differences\n"
+ "with the domain controller. "
+ "Please verify the system time.\n"));
_pam_log_debug(ctx, LOG_DEBUG,
"User %s: Clock skew when getting Krb5 TGT\n",
username);
@@ -1334,7 +1353,7 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
goto failed;
}
- str = talloc_asprintf(ctx, "Your password ");
+ str = talloc_asprintf(ctx, _("Your password "));
if (!str) {
goto failed;
}
@@ -1350,8 +1369,8 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
if (i->password_history > 0) {
str = talloc_asprintf_append(str,
- "cannot repeat any of your previous %d "
- "passwords; ",
+ _("cannot repeat any of your previous %d "
+ "passwords; "),
i->password_history);
if (!str) {
goto failed;
@@ -1360,19 +1379,19 @@ static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx,
if (i->password_properties & WBC_DOMAIN_PASSWORD_COMPLEX) {
str = talloc_asprintf_append(str,
- "must contain capitals, numerals "
- "or punctuation; "
- "and cannot contain your account "
- "or full name; ");
+ _("must contain capitals, numerals "
+ "or punctuation; "
+ "and cannot contain your account "
+ "or full name; "));
if (!str) {
goto failed;
}
}
str = talloc_asprintf_append(str,
- "Please type a different password. "
- "Type a password which meets these requirements in "
- "both text boxes.");
+ _("Please type a different password. "
+ "Type a password which meets these requirements in "
+ "both text boxes."));
if (!str) {
goto failed;
}
@@ -1855,8 +1874,8 @@ static int winbind_chauthtok_request(struct pwb_context *ctx,
break;
case WBC_PWD_CHANGE_REJECT_COMPLEXITY:
_make_remark(ctx, PAM_ERROR_MSG,
- "Password does not meet "
- "complexity requirements");
+ _("Password does not meet "
+ "complexity requirements"));
break;
default:
_pam_log_debug(ctx, LOG_DEBUG,
@@ -2489,7 +2508,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
}
retval = _winbind_read_password(ctx, ctx->ctrl, NULL,
- "Password: ", NULL,
+ _("Password: "), NULL,
&password);
if (retval != PAM_SUCCESS) {
@@ -2897,7 +2916,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/* instruct user what is happening */
-#define greeting "Changing password for"
+#define greeting _("Changing password for")
Announce = talloc_asprintf(ctx, "%s %s", greeting, user);
if (!Announce) {
_pam_log(ctx, LOG_CRIT,
@@ -2910,7 +2929,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD;
ret = _winbind_read_password(ctx, lctrl,
Announce,
- "(current) NT password: ",
+ _("(current) NT password: "),
NULL,
(const char **) &pass_old);
TALLOC_FREE(Announce);
@@ -2980,8 +2999,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
ret = _winbind_read_password(ctx, lctrl,
NULL,
- "Enter new NT password: ",
- "Retype new NT password: ",
+ _("Enter new NT password: "),
+ _("Retype new NT password: "),
(const char **)&pass_new);
if (ret != PAM_SUCCESS) {
diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h
index cb6f450ccb..0656f5972e 100644
--- a/source3/nsswitch/pam_winbind.h
+++ b/source3/nsswitch/pam_winbind.h
@@ -9,6 +9,7 @@
#include "system/time.h"
#include <talloc.h>
#include "libwbclient/wbclient.h"
+#include "localedir.h"
#define MODULE_NAME "pam_winbind"
#define PAM_SM_AUTH
@@ -22,6 +23,10 @@
#include <iniparser.h>
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#endif
+
#ifndef LINUX
/* Solaris always uses dynamic pam modules */
@@ -101,12 +106,20 @@ do { \
#define WINBIND_WARN_PWD_EXPIRE 0x00002000
#define WINBIND_MKHOMEDIR 0x00004000
+#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
+#define _(string) dgettext(MODULE_NAME, string)
+#else
+#define _(string) string
+#endif
+
+#define N_(string) string
+
/*
* here is the string to inform the user that the new passwords they
* typed were not the same.
*/
-#define MISTYPED_PASS "Sorry, passwords do not match"
+#define MISTYPED_PASS _("Sorry, passwords do not match")
#define on(x, y) (x & y)
#define off(x, y) (!(x & y))
diff --git a/source3/script/installmo.sh b/source3/script/installmo.sh
new file mode 100644
index 0000000000..a1f9c58e27
--- /dev/null
+++ b/source3/script/installmo.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+DESTDIR=$1
+LOCALEDIR=`echo $2 | sed 's/\/\//\//g'`
+SRCDIR=$3/
+MSGFMT=msgfmt
+
+case $0 in
+ *uninstall*)
+ if test ! -d "$DESTDIR/$LOCALEDIR"; then
+ echo "Directory $DESTDIR/$LOCALEDIR doesn't exist!"
+ echo "Do a \"make installmo\" or \"make install\" first."
+ exit 1
+ fi
+ mode='uninstall'
+ ;;
+ *)
+ mode='install'
+ ;;
+esac
+
+for dir in $SRCDIR/locale/*; do
+ MODULE=`basename $dir`
+ for f in $SRCDIR/locale/$MODULE/*.po; do
+ BASE=`basename $f`
+ LANGUAGE=`echo $BASE | sed 's/\.po//g'`
+ FNAME="$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/$MODULE.mo"
+ if test ! -d "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"; then
+ mkdir -p "$DESTDIR/$LOCALEDIR/$LANGUAGE/LC_MESSAGES/"
+ fi
+ if test "$mode" = 'install'; then
+ echo "Installing $f as $FNAME"
+ touch "$FNAME"
+ $MSGFMT "$f" -f -o "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges?"
+ exit 1
+ fi
+ chmod 0644 "$FNAME"
+ elif test "$mode" = 'uninstall'; then
+ echo "removing $FNAME"
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges?"
+ exit 1
+ fi
+ else
+ echo "Unknown mode $mode. script called as $0."
+ exit 1
+ fi
+ done
+ if test "$mode" = 'install'; then
+ cat << EOF
+==============================================================
+MO files for $MODULE are installed.
+==============================================================
+EOF
+ else
+ cat << EOF
+==============================================================
+MO files for $MODULE are removed.
+==============================================================
+EOF
+ fi
+done
+
+if test "$mode" = 'install'; then
+ cat << EOF
+==============================================================
+All MO files for Samba are installed. You can use "make uninstall"
+or "make uninstallmo" to remove them.
+==============================================================
+EOF
+else
+ cat << EOF
+==============================================================
+All MO files for Samba are removed. you can use "make install"
+or "make installmo" to install them.
+==============================================================
+EOF
+fi
+
+exit 0
diff --git a/source3/script/uninstallmo.sh b/source3/script/uninstallmo.sh
new file mode 100644
index 0000000000..5b4475f5c2
--- /dev/null
+++ b/source3/script/uninstallmo.sh
@@ -0,0 +1 @@
+installmo.sh