Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/passwd.cc')
-rw-r--r--winsup/cygwin/passwd.cc809
1 files changed, 0 insertions, 809 deletions
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc
deleted file mode 100644
index b8ed09466..000000000
--- a/winsup/cygwin/passwd.cc
+++ /dev/null
@@ -1,809 +0,0 @@
-/* passwd.cc: getpwnam () and friends
-
- Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
- 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#include "winsup.h"
-#include <lm.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "cygerrno.h"
-#include "security.h"
-#include "path.h"
-#include "fhandler.h"
-#include "dtable.h"
-#include "pinfo.h"
-#include "cygheap.h"
-#include "shared_info.h"
-#include "miscfuncs.h"
-#include "ldap.h"
-#include "tls_pbuf.h"
-
-/* Parse /etc/passwd line into passwd structure. */
-bool
-pwdgrp::parse_passwd ()
-{
- pg_pwd &res = passwd ()[curr_lines];
- res.p.pw_name = next_str (':');
- res.p.pw_passwd = next_str (':');
- if (!next_num (res.p.pw_uid))
- return false;
- if (!next_num (res.p.pw_gid))
- return false;
- res.p.pw_comment = NULL;
- res.p.pw_gecos = next_str (':');
- res.p.pw_dir = next_str (':');
- res.p.pw_shell = next_str (':');
- res.sid.getfrompw (&res.p);
- /* lptr points to the \0 after pw_shell. Increment by one to get the correct
- required buffer len in getpw_cp. */
- res.len = lptr - res.p.pw_name + 1;
- return true;
-}
-
-void
-pwdgrp::init_pwd ()
-{
- pwdgrp_buf_elem_size = sizeof (pg_pwd);
- parse = &pwdgrp::parse_passwd;
-}
-
-struct passwd *
-pwdgrp::find_user (cygpsid &sid)
-{
- for (ULONG i = 0; i < curr_lines; i++)
- if (sid == passwd ()[i].sid)
- return &passwd ()[i].p;
- return NULL;
-}
-
-struct passwd *
-pwdgrp::find_user (const char *name)
-{
- for (ULONG i = 0; i < curr_lines; i++)
- /* on Windows NT user names are case-insensitive */
- if (strcasematch (name, passwd ()[i].p.pw_name))
- return &passwd ()[i].p;
- return NULL;
-}
-
-struct passwd *
-pwdgrp::find_user (uid_t uid)
-{
- for (ULONG i = 0; i < curr_lines; i++)
- if (uid == passwd ()[i].p.pw_uid)
- return &passwd ()[i].p;
- return NULL;
-}
-
-struct passwd *
-internal_getpwsid (cygpsid &sid, cyg_ldap *pldap)
-{
- struct passwd *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.find_user (sid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ()
- && (ret = cygheap->pg.pwd_cache.file.find_user (sid)))
- return ret;
- if (cygheap->pg.nss_pwd_db ()
- && (ret = cygheap->pg.pwd_cache.win.find_user (sid)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.add_user_from_cygserver (sid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ())
- {
- cygheap->pg.pwd_cache.file.check_file ();
- if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (sid)))
- return ret;
- }
- if (cygheap->pg.nss_pwd_db ())
- return cygheap->pg.pwd_cache.win.add_user_from_windows (sid, pldap);
- return NULL;
-}
-
-/* This function gets only called from mkpasswd via cygwin_internal. */
-struct passwd *
-internal_getpwsid_from_db (cygpsid &sid)
-{
- cygheap->pg.nss_init ();
- return cygheap->pg.pwd_cache.win.add_user_from_windows (sid);
-}
-
-struct passwd *
-internal_getpwnam (const char *name, cyg_ldap *pldap)
-{
- struct passwd *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.find_user (name)))
- return ret;
- if (cygheap->pg.nss_pwd_files ()
- && (ret = cygheap->pg.pwd_cache.file.find_user (name)))
- return ret;
- if (cygheap->pg.nss_pwd_db ()
- && (ret = cygheap->pg.pwd_cache.win.find_user (name)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.add_user_from_cygserver (name)))
- return ret;
- if (cygheap->pg.nss_pwd_files ())
- {
- cygheap->pg.pwd_cache.file.check_file ();
- if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (name)))
- return ret;
- }
- if (cygheap->pg.nss_pwd_db ())
- return cygheap->pg.pwd_cache.win.add_user_from_windows (name, pldap);
- return NULL;
-}
-
-struct passwd *
-internal_getpwuid (uid_t uid, cyg_ldap *pldap)
-{
- struct passwd *ret;
-
- cygheap->pg.nss_init ();
- /* Check caches first. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.find_user (uid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ()
- && (ret = cygheap->pg.pwd_cache.file.find_user (uid)))
- return ret;
- if (cygheap->pg.nss_pwd_db ()
- && (ret = cygheap->pg.pwd_cache.win.find_user (uid)))
- return ret;
- /* Ask sources afterwards. */
- if (cygheap->pg.nss_cygserver_caching ()
- && (ret = cygheap->pg.pwd_cache.cygserver.add_user_from_cygserver (uid)))
- return ret;
- if (cygheap->pg.nss_pwd_files ())
- {
- cygheap->pg.pwd_cache.file.check_file ();
- if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (uid)))
- return ret;
- }
- if (cygheap->pg.nss_pwd_db () || uid == ILLEGAL_UID)
- return cygheap->pg.pwd_cache.win.add_user_from_windows (uid, pldap);
- return NULL;
-}
-
-/* getpwuid/getpwnam are not reentrant. */
-static struct {
- struct passwd p;
- char *buf;
- size_t bufsiz;
-} app_pw;
-
-static struct passwd *
-getpw_cp (struct passwd *temppw)
-{
- if (!temppw)
- return NULL;
- pg_pwd *pw = (pg_pwd *) temppw;
- if (app_pw.bufsiz < pw->len)
- {
- char *newbuf = (char *) realloc (app_pw.buf, pw->len);
- if (!newbuf)
- {
- set_errno (ENOMEM);
- return NULL;
- }
- app_pw.buf = newbuf;
- app_pw.bufsiz = pw->len;
- }
- memcpy (app_pw.buf, pw->p.pw_name, pw->len);
- memcpy (&app_pw.p, &pw->p, sizeof pw->p);
- ptrdiff_t diff = app_pw.buf - pw->p.pw_name;
- app_pw.p.pw_name += diff;
- app_pw.p.pw_passwd += diff;
- app_pw.p.pw_gecos += diff;
- app_pw.p.pw_dir += diff;
- app_pw.p.pw_shell += diff;
- return &app_pw.p;
-}
-
-extern "C" struct passwd *
-getpwuid32 (uid_t uid)
-{
- struct passwd *temppw = internal_getpwuid (uid);
- pthread_testcancel ();
- return getpw_cp (temppw);
-}
-
-#ifdef __x86_64__
-EXPORT_ALIAS (getpwuid32, getpwuid)
-#else
-extern "C" struct passwd *
-getpwuid (__uid16_t uid)
-{
- return getpwuid32 (uid16touid32 (uid));
-}
-#endif
-
-extern "C" int
-getpwuid_r32 (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
-{
- *result = NULL;
-
- if (!pwd || !buffer)
- return ERANGE;
-
- struct passwd *temppw = internal_getpwuid (uid);
- pthread_testcancel ();
- if (!temppw)
- return 0;
-
- /* check needed buffer size. */
- size_t needsize = strlen (temppw->pw_name) + strlen (temppw->pw_passwd)
- + strlen (temppw->pw_gecos) + strlen (temppw->pw_dir)
- + strlen (temppw->pw_shell) + 5;
- if (needsize > bufsize)
- return ERANGE;
-
- /* make a copy of temppw */
- *result = pwd;
- pwd->pw_uid = temppw->pw_uid;
- pwd->pw_gid = temppw->pw_gid;
- buffer = stpcpy (pwd->pw_name = buffer, temppw->pw_name);
- buffer = stpcpy (pwd->pw_passwd = buffer + 1, temppw->pw_passwd);
- buffer = stpcpy (pwd->pw_gecos = buffer + 1, temppw->pw_gecos);
- buffer = stpcpy (pwd->pw_dir = buffer + 1, temppw->pw_dir);
- stpcpy (pwd->pw_shell = buffer + 1, temppw->pw_shell);
- pwd->pw_comment = NULL;
- return 0;
-}
-
-#ifdef __x86_64__
-EXPORT_ALIAS (getpwuid_r32, getpwuid_r)
-#else
-extern "C" int
-getpwuid_r (__uid16_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
-{
- return getpwuid_r32 (uid16touid32 (uid), pwd, buffer, bufsize, result);
-}
-#endif
-
-extern "C" struct passwd *
-getpwnam (const char *name)
-{
- struct passwd *temppw = internal_getpwnam (name);
- pthread_testcancel ();
- return getpw_cp (temppw);
-}
-
-
-/* the max size buffer we can expect to
- * use is returned via sysconf with _SC_GETPW_R_SIZE_MAX.
- * This may need updating! - Rob Collins April 2001.
- */
-extern "C" int
-getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result)
-{
- *result = NULL;
-
- if (!pwd || !buffer || !nam)
- return ERANGE;
-
- struct passwd *temppw = internal_getpwnam (nam);
- pthread_testcancel ();
-
- if (!temppw)
- return 0;
-
- /* check needed buffer size. */
- size_t needsize = strlen (temppw->pw_name) + strlen (temppw->pw_passwd)
- + strlen (temppw->pw_gecos) + strlen (temppw->pw_dir)
- + strlen (temppw->pw_shell) + 5;
- if (needsize > bufsize)
- return ERANGE;
-
- /* make a copy of temppw */
- *result = pwd;
- pwd->pw_uid = temppw->pw_uid;
- pwd->pw_gid = temppw->pw_gid;
- buffer = stpcpy (pwd->pw_name = buffer, temppw->pw_name);
- buffer = stpcpy (pwd->pw_passwd = buffer + 1, temppw->pw_passwd);
- buffer = stpcpy (pwd->pw_gecos = buffer + 1, temppw->pw_gecos);
- buffer = stpcpy (pwd->pw_dir = buffer + 1, temppw->pw_dir);
- stpcpy (pwd->pw_shell = buffer + 1, temppw->pw_shell);
- pwd->pw_comment = NULL;
- return 0;
-}
-
-/* getpwent functions are not reentrant. */
-static pw_ent pwent;
-
-void
-pg_ent::clear_cache ()
-{
- if (pg.curr_lines)
- {
- if (state > from_file)
- cfree (group ? grp.g.gr_name : pwd.p.pw_name);
- pg.curr_lines = 0;
- }
-}
-
-void
-pg_ent::setent (bool _group, int _enums, PCWSTR _enum_tdoms)
-{
- cygheap->dom.init ();
- endent (_group);
- if (!_enums && !_enum_tdoms)
- {
- /* This is the default, when called from the usual setpwent/setgrent
- functions. */
- enums = cygheap->pg.nss_db_enums ();
- enum_tdoms = cygheap->pg.nss_db_enum_tdoms ();
- if (_group)
- {
- from_files = cygheap->pg.nss_grp_files ();
- from_db = cygheap->pg.nss_grp_db ();
- }
- else
- {
- from_files = cygheap->pg.nss_pwd_files ();
- from_db = cygheap->pg.nss_pwd_db ();
- }
- }
- else
- {
- /* This case is when called from mkpasswd/mkgroup via cygwin_internal. */
- enums = _enums;
- enum_tdoms = _enum_tdoms;
- from_files = false;
- from_db = true;
- }
- state = from_cache;
-}
-
-void *
-pg_ent::getent (void)
-{
- void *entry;
-
- switch (state)
- {
- case rewound:
- state = from_cache;
- /*FALLTHRU*/
- case from_cache:
- if (nss_db_enum_caches ()
- && (entry = enumerate_caches ()))
- return entry;
- state = from_file;
- /*FALLTHRU*/
- case from_file:
- if (from_files
- && nss_db_enum_files ()
- && (entry = enumerate_file ()))
- return entry;
- state = from_builtin;
- /*FALLTHRU*/
- case from_builtin:
- if (from_db
- && nss_db_enum_builtin ()
- && (entry = enumerate_builtin ()))
- return entry;
- state = from_local;
- /*FALLTHRU*/
- case from_local:
- if (from_db
- && nss_db_enum_local ()
- && (!cygheap->dom.member_machine ()
- || !nss_db_enum_primary ())
- && (entry = enumerate_local ()))
- return entry;
- state = from_sam;
- /*FALLTHRU*/
- case from_sam:
- if (from_db
- && nss_db_enum_local ()
- /* Domain controller? If so, sam and ad are one and the same
- and "local ad" would list all domain accounts twice without
- this test. */
- && (cygheap->dom.account_flat_name ()[0] != L'@'
- || !nss_db_enum_primary ())
- && (entry = enumerate_sam ()))
- return entry;
- state = from_ad;
- /*FALLTHRU*/
- case from_ad:
- if (cygheap->dom.member_machine ()
- && from_db
- && (entry = enumerate_ad ()))
- return entry;
- state = finished;
- /*FALLTHRU*/
- case finished:
- break;
- }
- return NULL;
-}
-
-void
-pg_ent::endent (bool _group)
-{
- if (buf)
- {
- if (state == from_file)
- free (buf);
- else if (state == from_local || state == from_sam)
- NetApiBufferFree (buf);
- buf = NULL;
- }
- if (!pg.curr_lines)
- {
- if ((group = _group))
- {
- pg.init_grp ();
- pg.pwdgrp_buf = (void *) &grp;
- }
- else
- {
- pg.init_pwd ();
- pg.pwdgrp_buf = (void *) &pwd;
- }
- pg.max_lines = 1;
- }
- else
- clear_cache ();
- cldap.close ();
- rl.close ();
- cnt = max = resume = 0;
- enums = 0;
- enum_tdoms = NULL;
- state = rewound;
-}
-
-void *
-pg_ent::enumerate_file ()
-{
- void *entry;
-
- if (!cnt)
- {
- pwdgrp &prf = group ? cygheap->pg.grp_cache.file
- : cygheap->pg.pwd_cache.file;
- if (prf.check_file ())
- {
- if (!buf)
- buf = (char *) malloc (NT_MAX_PATH);
- if (buf
- && !rl.init (prf.file_attr (), buf, NT_MAX_PATH))
- {
- free (buf);
- buf = NULL;
- }
- }
- }
- ++cnt;
- if ((entry = pg.add_account_post_fetch (rl.gets (), false)))
- return entry;
- rl.close ();
- free (buf);
- buf = NULL;
- cnt = max = resume = 0;
- return NULL;
-}
-
-void *
-pg_ent::enumerate_builtin ()
-{
- static cygpsid *pwd_builtins[] = {
- &well_known_system_sid,
- &well_known_local_service_sid,
- &well_known_network_service_sid,
- &well_known_admins_sid,
- &trusted_installer_sid,
- NULL
- };
- static cygpsid *grp_builtins[] = {
- &well_known_system_sid,
- &trusted_installer_sid,
- NULL
- };
-
- cygpsid **builtins = group ? grp_builtins : pwd_builtins;
- if (!builtins[cnt])
- {
- cnt = max = resume = 0;
- return NULL;
- }
- cygsid sid (*builtins[cnt++]);
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = pg.fetch_account_from_windows (arg);
- return pg.add_account_post_fetch (line, false);
-}
-
-void *
-pg_ent::enumerate_sam ()
-{
- while (true)
- {
- if (!cnt)
- {
- DWORD total;
- NET_API_STATUS ret;
-
- if (buf)
- {
- NetApiBufferFree (buf);
- buf = NULL;
- }
- if (resume == ULONG_MAX)
- ret = ERROR_NO_MORE_ITEMS;
- else if (group)
- ret = NetGroupEnum (NULL, 2, (PBYTE *) &buf, MAX_PREFERRED_LENGTH,
- &max, &total, &resume);
- else
- ret = NetUserEnum (NULL, 20, FILTER_NORMAL_ACCOUNT, (PBYTE *) &buf,
- MAX_PREFERRED_LENGTH, &max, &total,
- (PDWORD) &resume);
- if (ret == NERR_Success)
- resume = ULONG_MAX;
- else if (ret != ERROR_MORE_DATA)
- {
- cnt = max = resume = 0;
- return NULL;
- }
- }
- while (cnt < max)
- {
- cygsid sid (cygheap->dom.account_sid ());
- sid_sub_auth (sid, sid_sub_auth_count (sid)) =
- group ? ((PGROUP_INFO_2) buf)[cnt].grpi2_group_id
- : ((PUSER_INFO_20) buf)[cnt].usri20_user_id;
- ++cnt;
- ++sid_sub_auth_count (sid);
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = pg.fetch_account_from_windows (arg);
- if (line)
- return pg.add_account_post_fetch (line, false);
- }
- cnt = 0;
- }
-}
-
-void *
-pg_ent::enumerate_ad ()
-{
- while (true)
- {
- if (!cnt)
- {
- PDS_DOMAIN_TRUSTSW td;
-
- if (!resume)
- {
- ++resume;
- if (!nss_db_enum_primary ()
- || cldap.enumerate_ad_accounts (NULL, group) != NO_ERROR)
- continue;
- }
- else if ((td = cygheap->dom.trusted_domain (resume - 1)))
- {
- ++resume;
- /* Ignore primary domain in list of trusted domains only if all
- trusted domains are enumerated anyway. This handles an
- annoying backward compatibility problem in mkpasswd/mkgroup.
- Without this test, `mkpasswd -d PRIMARY_DOMAIN' wouldn't
- work as expected. */
- if (((enums & ENUM_TDOMS_ALL) && td->Flags & DS_DOMAIN_PRIMARY)
- || !td->DomainSid
- || (!nss_db_enum_tdom (td->NetbiosDomainName)
- && !nss_db_enum_tdom (td->DnsDomainName))
- || cldap.enumerate_ad_accounts (td->DnsDomainName, group)
- != NO_ERROR)
- continue;
- }
- else
- {
- cldap.close ();
- return NULL;
- }
- }
- ++cnt;
- cygsid sid;
- int ret = cldap.next_account (sid);
- if (ret == NO_ERROR)
- {
- fetch_user_arg_t arg;
- arg.type = SID_arg;
- arg.sid = &sid;
- char *line = pg.fetch_account_from_windows (arg, &cldap);
- if (line)
- return pg.add_account_post_fetch (line, false);
- ret = EIO;
- }
- if (ret != ENMFILE)
- {
- cldap.close ();
- set_errno (ret);
- return NULL;
- }
- cnt = 0;
- }
-}
-
-void *
-pw_ent::enumerate_caches ()
-{
- switch (max)
- {
- case 0:
- if (cygheap->pg.nss_cygserver_caching ())
- {
- pwdgrp &prc = cygheap->pg.pwd_cache.cygserver;
- if (cnt < prc.cached_users ())
- return &prc.passwd ()[cnt++].p;
- }
- cnt = 0;
- max = 1;
- /*FALLTHRU*/
- case 1:
- if (from_files)
- {
- pwdgrp &prf = cygheap->pg.pwd_cache.file;
- prf.check_file ();
- if (cnt < prf.cached_users ())
- return &prf.passwd ()[cnt++].p;
- }
- cnt = 0;
- max = 2;
- /*FALLTHRU*/
- default:
- if (from_db)
- {
- pwdgrp &prw = cygheap->pg.pwd_cache.win;
- if (cnt < prw.cached_users ())
- return &prw.passwd ()[cnt++].p;
- }
- break;
- }
- cnt = max = 0;
- return NULL;
-}
-
-void *
-pw_ent::enumerate_local ()
-{
- return NULL;
-}
-
-struct passwd *
-pw_ent::getpwent (void)
-{
- if (state == rewound)
- setent (false);
- else
- clear_cache ();
- return (struct passwd *) getent ();
-}
-
-extern "C" void
-setpwent ()
-{
- pwent.setpwent ();
-}
-
-extern "C" struct passwd *
-getpwent (void)
-{
- return pwent.getpwent ();
-}
-
-extern "C" void
-endpwent (void)
-{
- pwent.endpwent ();
-}
-
-/* *_filtered functions are called from mkpasswd */
-void *
-setpwent_filtered (int enums, PCWSTR enum_tdoms)
-{
- pw_ent *pw = new pw_ent;
- if (pw)
- pw->setpwent (enums, enum_tdoms);
- return (void *) pw;
-}
-
-void *
-getpwent_filtered (void *pw)
-{
- return (void *) ((pw_ent *) pw)->getpwent ();
-}
-
-void
-endpwent_filtered (void *pw)
-{
- ((pw_ent *) pw)->endpwent ();
-}
-
-#ifndef __x86_64__
-extern "C" struct passwd *
-getpwduid (__uid16_t)
-{
- return NULL;
-}
-#endif
-
-extern "C" int
-setpassent (int)
-{
- return 0;
-}
-
-static void
-_getpass_close_fd (void *arg)
-{
- if (arg)
- fclose ((FILE *) arg);
-}
-
-extern "C" char *
-getpass (const char * prompt)
-{
- char *pass = _my_tls.locals.pass;
- struct termios ti, newti;
- bool tc_set = false;
-
- /* Try to use controlling tty in the first place. Use stdin and stderr
- only as fallback. */
- FILE *in = stdin, *err = stderr;
- FILE *tty = fopen ("/dev/tty", "w+b");
- pthread_cleanup_push (_getpass_close_fd, tty);
- if (tty)
- {
- /* Set close-on-exec for obvious reasons. */
- fcntl (fileno (tty), F_SETFD, fcntl (fileno (tty), F_GETFD) | FD_CLOEXEC);
- in = err = tty;
- }
-
- /* Make sure to notice if stdin is closed. */
- if (fileno (in) >= 0)
- {
- flockfile (in);
- /* Change tty attributes if possible. */
- if (!tcgetattr (fileno (in), &ti))
- {
- newti = ti;
- newti.c_lflag &= ~(ECHO | ISIG); /* No echo, no signal handling. */
- if (!tcsetattr (fileno (in), TCSANOW, &newti))
- tc_set = true;
- }
- fputs (prompt, err);
- fflush (err);
- fgets (pass, _PASSWORD_LEN, in);
- fprintf (err, "\n");
- if (tc_set)
- tcsetattr (fileno (in), TCSANOW, &ti);
- funlockfile (in);
- char *crlf = strpbrk (pass, "\r\n");
- if (crlf)
- *crlf = '\0';
- }
- pthread_cleanup_pop (1);
- return pass;
-}