Esempio n. 1
0
void
LM::Presentity::edit_presentity ()
{
  boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&LM::Presentity::edit_presentity_form_submitted, this, _1, _2)));

  request->title (_("Edit roster element"));
  request->instructions (_("Please fill in this form to change an existing "
			   "element of the remote roster"));
  request->text ("name", _("Name:"), get_name (), std::string ());

  request->editable_set ("groups", _("Choose groups:"),
			 get_groups (), get_groups ());

  questions (request);
}
Esempio n. 2
0
void
Local::Presentity::edit_presentity ()
{
  ClusterPtr cluster = local_cluster.lock ();

  if (!cluster)
    return;

  boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&Local::Presentity::edit_presentity_form_submitted, this, _1, _2)));

  std::string name = get_name ();
  std::string uri = get_uri ();
  std::set<std::string> groups = get_groups ();
  std::set<std::string> all_groups = cluster->existing_groups ();

  request->title (_("Edit roster element"));
  request->instructions (_("Please fill in this form to change an existing "
			   "element of ekiga's internal roster"));
  request->text ("name", _("Name:"), name, _("Name of the contact, as shown in your roster"));
  request->text ("uri", _("Address:"), uri, _("Address, e.g. sip:[email protected]; if you do not specify the host part, e.g. sip:xyz, then you can choose it by right-clicking on the contact in roster"));
  request->boolean ("preferred", _("Is a preferred contact"), is_preferred ());

  request->editable_set ("groups", _("Choose groups:"),
			 groups, all_groups);

  questions (request);
}
void editor_palette<Item>::expand_palette_groups_menu(std::vector<config>& items, int i)
{
	auto pos = items.erase(items.begin() + i);

	std::vector<config> groups;
	const std::vector<item_group>& item_groups = get_groups();

	for (std::size_t mci = 0; mci < item_groups.size(); ++mci) {
		std::string groupname = item_groups[mci].name;
		if (groupname.empty()) {
			groupname = _("(Unknown Group)");
		}
		std::string img = item_groups[mci].icon + "_30";
		if (mci == active_group_index()) {
			std::string pressed_img = img + "-pressed.png";
			if(!filesystem::get_binary_file_location("images", pressed_img).empty()) {
				img = pressed_img;
			} else {
				img += ".png~CS(70,70,0)";
			}
		} else {
			img += ".png";
		}

		groups.emplace_back(
			"label", groupname,
			"icon", img
		);
	}

	items.insert(pos, groups.begin(), groups.end());
}
Esempio n. 4
0
void
Opal::Presentity::edit_presentity ()
{
  boost::shared_ptr<Ekiga::FormRequestSimple> request =
    boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&Opal::Presentity::edit_presentity_form_submitted, this, _1, _2, _3)));

  /* Translators: This is Edit name of the contact
   * e.g. Editing Contact Claire Fleury.
   */
  char *title = g_strdup_printf (_("Editing Contact %s"), get_name ().c_str ());
  request->title (title);
  g_free (title);

  request->action (_("Done"));
  request->text ("name", _("Name"),
                 get_name (),
                 _("John Doe"),
                 Ekiga::FormVisitor::STANDARD,
                 false, false);
  request->text ("uri", _("URI"),
                 get_uri (),
                 _("sip:[email protected]"),
                 Ekiga::FormVisitor::URI,
                 false, false);

  request->editable_list ("groups", _("Groups"),
                          get_groups (), existing_groups ());

  questions (request);
}
Esempio n. 5
0
void mesos::on_watch_data(const std::string& framework_id, mesos_event_data&& msg)
{
	// if this is marathon task status update, we need to get the labels
	// from mesos because the update message does not contain them
	// TODO (maybe): refactor to keep labels in apps and have tasks labels updated
	// when tasks are asigned to apps
	add_task_labels(msg.get_data());

	// if this is group change, replace event data (which does not contain enough
	// information to rebuild state) with Marathon state API JSON
	for(auto& http : m_marathon_groups_http)
	{
		if(http.second->get_id() == framework_id)
		{
			get_groups(http.second, msg.get_data());
		}
	}

	for(auto& dispatcher : m_dispatch)
	{
		if(framework_id == dispatcher.second->get_id())
		{
			dispatcher.second->enqueue(std::move(msg));
			break;
		}
	}
}
Esempio n. 6
0
int
main(void)
{
	long rc;

	/* check how the first argument is decoded */
	ngroups = syscall(SYSCALL_NR, 0, 0);
	printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, ngroups);
	if (ngroups < 0)
		perror_msg_and_fail(SYSCALL_NAME);

	rc = syscall(SYSCALL_NR, (long) 0xffffffff00000000ULL, 0);
	printf("%s(0, NULL) = %ld\n", SYSCALL_NAME, rc);

	rc = syscall(SYSCALL_NR, -1U, 0);
	printf("%s(%u, NULL) = %s\n", SYSCALL_NAME, -1U, sprintrc(rc));

	rc = syscall(SYSCALL_NR, -1L, 0);
	printf("%s(%u, NULL) = %s\n", SYSCALL_NAME, -1U, sprintrc(rc));

	const unsigned int ngroups_max = sysconf(_SC_NGROUPS_MAX);

	rc = syscall(SYSCALL_NR, ngroups_max, 0);
	printf("%s(%u, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc));

	rc = syscall(SYSCALL_NR, (long) 0xffffffff00000000ULL | ngroups_max, 0);
	printf("%s(%u, NULL) = %s\n", SYSCALL_NAME, ngroups_max, sprintrc(rc));

	/* check how the second argument is decoded */
	GID_TYPE *const g1 =
		tail_alloc(ngroups ? sizeof(*g1) * ngroups : 1);
	GID_TYPE *const g2 = tail_alloc(sizeof(*g2) * (ngroups + 1));
	void *efault = g2 + ngroups + 1;

	get_groups(ngroups, g1);
	get_groups(ngroups + 1, g1);
	get_groups(ngroups + 1, g2);

	if (ngroups) {
		rc = syscall(SYSCALL_NR, ngroups, efault);
		printf("%s(%u, %p) = %s\n",
		       SYSCALL_NAME, (unsigned) ngroups, efault, sprintrc(rc));
	}

	puts("+++ exited with 0 +++");
	return 0;
}
Esempio n. 7
0
static struct custom_data *decode_custom_data(unsigned char *buf, int len, struct custom_data *d)
{
    gint ix = 0;
    gboolean err = FALSE;
    LOG("%s: len=%d", __FUNCTION__, len);

    while (ix < len && !err) {
        LOG("buf[%d]=0x%02x=%d", ix, buf[ix], buf[ix]);

        switch (buf[ix++]) {
        case CD_VERSION: { 
            gint ver;
            ix += get_byte(&(buf[ix]), &ver);
            if (ver != 0) ERROR("Wrong version %d", ver);
        }
            break;
        case CD_NAME_LONG:
            LOG("CD_NAME_LONG");
            ix += get_string(&(buf[ix]), d->name_long);
            break;
       case CD_NAME_SHORT:
            LOG("CD_NAME_SHORT");
            ix += get_string(&(buf[ix]), d->name_short);
            break;
        case CD_COMPETITORS_MIN:
            GET_SHORT(d->competitors_min);
            LOG("CD_COMPETITORS_MIN = %d", d->competitors_min);
            break;
        case CD_COMPETITORS_MAX:
            GET_SHORT(d->competitors_max);
            LOG("CD_COMPETITORS_MAX = %d", d->competitors_max);
            break;
        case CD_NUM_RR_POOLS:
            LOG("CD_NUM_RR_POOLS");
            ix += get_rr_pools(&(buf[ix]), d, &err);
            break;
        case CD_NUM_MATCHES:
            LOG("CD_NUM_MATCHES");
            ix += get_matches(&(buf[ix]), d, &err);
            break;
        case CD_NUM_POSITIONS:
            LOG("CD_NUM_POSITIONS");
            ix += get_positions(&(buf[ix]), d, &err);
            break;
        case CD_NUM_B3_POOLS:
            ix += get_best_of_three_pairs(&(buf[ix]), d, &err);
            break;
        case CD_NUM_GROUPS:
            ix += get_groups(&(buf[ix]), d, &err);
            break;
        default:
            g_print("Unknown CD type %d\n", buf[ix-1]);
            return NULL;
        }
    }

    if (err) return NULL;
    return d;
}
Esempio n. 8
0
Array Node::_get_groups() const {

	Array groups;
	List<GroupInfo> gi;
	get_groups(&gi);
	for (List<GroupInfo>::Element *E=gi.front();E;E=E->next()) {
		groups.push_back(E->get().name);
	}

	return groups;
}
Esempio n. 9
0
static inline void enter_user_context_real()
{
	gid_t *groups;
	size_t ngroups;
	struct fuse_context *c = fuse_get_context();

	if (!single_threaded || geteuid())
		return;
	if ((ngroups = get_groups(c->pid, &groups))) {
		setgroups(ngroups, groups);
		free(groups);
	}
	setregid(c->gid, -1);
	setreuid(c->uid, -1);
}
Esempio n. 10
0
bool
passwd_cache::init_groups( const char* user, gid_t additional_gid ) {

	gid_t *gid_list;
	bool result;
	int siz;

	siz = num_groups(user);
	result = true;
	gid_list = NULL;

	if ( siz > 0 ) {

		gid_list = new gid_t[siz + 1];

		if ( get_groups(user, siz, gid_list) ) { 

			if (additional_gid != 0) {
				gid_list[siz] = additional_gid;
				siz++;
			}

			if ( setgroups(siz, gid_list) != 0 ) {
				dprintf(D_ALWAYS, "passwd_cache: setgroups( %s ) failed.\n", user);
				result = false;
			} else {
					/* success */
				result = true;			
			}
			
		} else {
			dprintf(D_ALWAYS, "passwd_cache: getgroups( %s ) failed.\n", user);
			result = false;
		}

	} else {
			/* error */
		dprintf(D_ALWAYS,
		        "passwd_cache: num_groups( %s ) returned %d\n",
		        user,
		        siz);
		result = false;
	}

	if ( gid_list ) { delete[] gid_list; }
	return result;
}
Esempio n. 11
0
void Node::generate_instance_state() {

	List<PropertyInfo> properties;
	get_property_list(&properties);

	data.instance_state.clear();

	for( List<PropertyInfo>::Element *E=properties.front();E;E=E->next() ) {

		PropertyInfo &pi=E->get();
		if ((pi.usage&PROPERTY_USAGE_NO_INSTANCE_STATE) || !(pi.usage&PROPERTY_USAGE_EDITOR) || !(pi.usage&PROPERTY_USAGE_STORAGE))
			continue;

		data.instance_state[pi.name]=get(pi.name);
	}

	List<GroupInfo> groups;
	get_groups(&groups);
	for(List<GroupInfo>::Element *E=groups.front();E;E=E->next()) {

		if (!E->get().persistent)
			continue;
		data.instance_groups.push_back(E->get().name);
	}

	List<MethodInfo> signal_list;

	get_signal_list(&signal_list);

	for(List<MethodInfo>::Element *E=signal_list.front();E;E=E->next()) {

		StringName name = E->get().name;
		List<Connection> connections;
		get_signal_connection_list(name,&connections);

		for(List<Connection>::Element *F=connections.front();F;F=F->next()) {

			if (F->get().flags&CONNECT_PERSIST)
				data.instance_connections.push_back(F->get());
		}

	}
}
Esempio n. 12
0
/**
 * The main test program.
 */
void
piglit_init(int argc, char **argv)
{
	unsigned *groups;
	int num_groups;

	piglit_require_extension("GL_AMD_performance_monitor");

	/* Basic glGetPerfMonitorGroupsAMD() tests */
	get_groups(&groups, &num_groups);

	/* If there are no groups, the rest of the tests can't run.  Bail. */
	if (num_groups == 0)
		exit(0);

	test_basic_measurement(groups[0]);
	test_change_counters_while_active(groups[0]);

	exit(0);
}
Esempio n. 13
0
bool GUser_Data_Tools::reindex_group(Group_Data * group)
{
	//remove all "old" index values for that group
	gip_storage_hash::iterator it;
	for (it=group_index.begin(); it != group_index.end(); it++) {
		guser_data_list_vector *mylist = (*it).second;
		guser_data_list_vector::iterator it2;
		//(*mylist).clear(); ?! we can simply drop all
		for (it2=(*mylist).begin(); it2 != (*mylist).end(); it2++) {
			if ((*it2) == group) {
				(*it2) = NULL; //we dont want the erase to handle something dirty here
				(*mylist).erase(it2);
				break;
			}
		}
	}

	//readd them all
	guser_data_list_idx *members = group->get_members();
	guser_data_list_idx::iterator it2;
	for (it2=members->begin(); it2 != members->end(); it2++) {
		guser_data_idx member = (*it2);
		guser_data_list_vector *mylist = get_groups(&member.saddr,&member.vlan_id);
		if (mylist) {
			//add in old vector
			(*mylist).push_back(group);
		} else {
			//we need to add a new vector to the hash
			guser_data_list_vector *newlist = new guser_data_list_vector;
			(*newlist).push_back(group);
			group_index.insert(pair<struct guser_data_idx, guser_data_list_vector*>(member, newlist));
		}
	}

	return true;	
}
Esempio n. 14
0
void
Local::Presentity::edit_presentity_form_submitted (bool submitted,
						   Ekiga::Form &result)
{
  if (!submitted)
    return;

  const std::string new_name = result.text ("name");
  const std::set<std::string> groups = get_groups ();
  const std::set<std::string> new_groups = result.editable_set ("groups");
  std::string new_uri = result.text ("uri");
  const std::string uri = get_uri ();
  bool preferred = result.boolean ("preferred");
  std::set<xmlNodePtr> nodes_to_remove;

  new_uri = canonize_uri (new_uri);

  for (xmlNodePtr child = node->children ;
       child != NULL ;
       child = child->next) {

    if (child->type == XML_ELEMENT_NODE
        && child->name != NULL) {

      if (xmlStrEqual (BAD_CAST ("name"), child->name)) {

	robust_xmlNodeSetContent (node, &child, "name", new_name);
      }
    }
  }

  if (uri != new_uri) {

    boost::shared_ptr<Ekiga::PresenceCore> pcore = presence_core.lock ();
    if (pcore) {
      pcore->unfetch_presence (uri);
      pcore->fetch_presence (new_uri);
    }
    presence = "unknown";
    xmlSetProp (node, (const xmlChar*)"uri", (const xmlChar*)new_uri.c_str ());
  }

  // the first loop looks at groups we were in : are we still in ?
  for (xmlNodePtr child = node->children ;
       child != NULL ;
       child = child->next) {

    if (child->type == XML_ELEMENT_NODE
        && child->name != NULL) {

      if (xmlStrEqual (BAD_CAST ("group"), child->name)) {

	xmlChar* xml_str = xmlNodeGetContent (child);

	if (xml_str != NULL) {

	  if (new_groups.find ((const char*) xml_str) == new_groups.end ()) {

	    nodes_to_remove.insert (child); // don't free what we loop on!
	  }
	  xmlFree (xml_str);
	}
      }
    }
  }

  // ok, now we can clean up!
  for (std::set<xmlNodePtr>::iterator iter = nodes_to_remove.begin ();
       iter != nodes_to_remove.end ();
       ++iter) {

    xmlUnlinkNode (*iter);
    xmlFreeNode (*iter);
  }

  // the second loop looking for groups we weren't in but are now
  for (std::set<std::string>::const_iterator iter = new_groups.begin ();
       iter != new_groups.end ();
       iter++) {

    if (std::find (groups.begin (), groups.end (), *iter) == groups.end ()) {
      xmlNewChild (node, NULL,
		   BAD_CAST "group",
		   BAD_CAST robust_xmlEscape (node->doc, *iter).c_str ());
    }
  }

  if (preferred) {

    xmlSetProp (node, BAD_CAST "preferred", BAD_CAST "true");
  } else {

    xmlSetProp (node, BAD_CAST "preferred", BAD_CAST "false");
  }

  updated ();
  trigger_saving ();
}
Esempio n. 15
0
int
main(int argc, char * const argv[])
{
	int o;

	while ((o = getopt(argc, argv, "adg:l:mopstux")) != -1)
		switch (o) {
		case 'a':
			a_flag = 1;
			break;
		case 'd':
			everything = 0;
			d_flag = 1;
			break;
		case 'g':
			everything = 0;
			g_args = optarg;
			break;
		case 'l':
			everything = 0;
			l_args = optarg;
			break;
		case 'm':
			m_flag = 1;
			break;
		case 'o':
			o_flag = 1;
			break;
		case 'p':
			everything = 0;
			p_flag = 1;
			break;
		case 's':
			everything = 0;
			s_flag = 1;
			break;
		case 't':
			t_flag = 1;
			break;
		case 'u':
			everything = 0;
			u_flag = 1;
			break;
		case 'x':
			x_flag = 1;
			break;
		default:
			usage();
		}

	argc -= optind;
	argv += optind;

	if (argc > 0)
		usage();

	get_groups();
	get_users();
	select_users();
	sort_users();
	list_users();
	exit(0);
}
Esempio n. 16
0
File: id.c Progetto: nawawi/busybox
int id_main(int argc UNUSED_PARAM, char **argv)
{
	uid_t ruid;
	gid_t rgid;
	uid_t euid;
	gid_t egid;
	unsigned opt;
	int i;
	int status = EXIT_SUCCESS;
	const char *prefix;
	const char *username;
#if ENABLE_SELINUX
	security_context_t scontext = NULL;
#endif

	if (ENABLE_GROUPS && (!ENABLE_ID || applet_name[0] == 'g')) {
		/* TODO: coreutils groups prepend "USER : "******"") | JUST_ALL_GROUPS | NAME_NOT_NUMBER;
	} else {
		/* Don't allow -n -r -nr -ug -rug -nug -rnug -uZ -gZ -GZ*/
		/* Don't allow more than one username */
		opt = getopt32(argv, "^"
			"rnugG" IF_SELINUX("Z")
			"\0"
			"?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG"
			IF_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G")
		);
	}

	username = argv[optind];
	if (username) {
		struct passwd *p = xgetpwnam(username);
		euid = ruid = p->pw_uid;
		egid = rgid = p->pw_gid;
	} else {
		egid = getegid();
		rgid = getgid();
		euid = geteuid();
		ruid = getuid();
	}
	/* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */
	/* id says: print the real ID instead of the effective ID, with -ugG */
	/* in fact in this case egid is always printed if egid != rgid */
	if (!opt || (opt & JUST_ALL_GROUPS)) {
		gid_t *groups;
		int n;

		if (!opt) {
			/* Default Mode */
			status |= print_user(ruid, "uid=");
			status |= print_group(rgid, " gid=");
			if (euid != ruid)
				status |= print_user(euid, " euid=");
			if (egid != rgid)
				status |= print_group(egid, " egid=");
		} else {
			/* JUST_ALL_GROUPS */
			status |= print_group(rgid, NULL);
			if (egid != rgid)
				status |= print_group(egid, " ");
		}
		/* We are supplying largish buffer, trying
		 * to not run get_groups() twice. That might be slow
		 * ("user database in remote SQL server" case) */
		groups = xmalloc(64 * sizeof(groups[0]));
		n = 64;
		if (get_groups(username, rgid, groups, &n) < 0) {
			/* Need bigger buffer after all */
			groups = xrealloc(groups, n * sizeof(groups[0]));
			get_groups(username, rgid, groups, &n);
		}
		if (n > 0) {
			/* Print the list */
			prefix = " groups=";
			for (i = 0; i < n; i++) {
				if (opt && (groups[i] == rgid || groups[i] == egid))
					continue;
				status |= print_group(groups[i], opt ? " " : prefix);
				prefix = ",";
			}
		} else if (n < 0) { /* error in get_groups() */
			if (ENABLE_DESKTOP)
				bb_error_msg_and_die("can't get groups");
			return EXIT_FAILURE;
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			free(groups);
#if ENABLE_SELINUX
		if (is_selinux_enabled()) {
			if (getcon(&scontext) == 0)
				printf(" context=%s", scontext);
		}
#endif
	} else if (opt & PRINT_REAL) {
		euid = ruid;
		egid = rgid;
	}

	if (opt & JUST_USER)
		status |= print_user(euid, NULL);
	else if (opt & JUST_GROUP)
		status |= print_group(egid, NULL);
#if ENABLE_SELINUX
	else if (opt & JUST_CONTEXT) {
		selinux_or_die();
		if (username || getcon(&scontext)) {
			bb_error_msg_and_die("can't get process context%s",
				username ? " for a different user" : "");
		}
		fputs(scontext, stdout);
	}
	/* freecon(NULL) seems to be harmless */
	if (ENABLE_FEATURE_CLEAN_UP)
		freecon(scontext);
#endif
	bb_putchar('\n');
	fflush_stdout_and_exit(status);
}
Esempio n. 17
0
bool
Opal::Presentity::edit_presentity_form_submitted (bool submitted,
                                                  Ekiga::Form &result,
                                                  std::string &error)
{
  if (!submitted)
    return false;

  const std::string new_name = result.text ("name");
  const std::list<std::string> groups = get_groups ();
  const std::list<std::string> new_groups = result.editable_list ("groups");
  std::string new_uri = result.text ("uri");
  const std::string uri = get_uri ();
  std::set<xmlNodePtr> nodes_to_remove;

  if (new_name.empty ()) {
    error = _("You did not provide a valid name");
    return false;
  }
  else if (new_uri.empty ()) {
    error = _("You did not provide a valid address");
    return false;
  }

  new_uri = canonize_uri (new_uri);

  for (xmlNodePtr child = node->children ;
       child != NULL ;
       child = child->next) {

    if (child->type == XML_ELEMENT_NODE
        && child->name != NULL)
      if (xmlStrEqual (BAD_CAST ("name"), child->name))
        robust_xmlNodeSetContent (node, &child, "name", new_name);
  }

  if (uri != new_uri) {
    xmlSetProp (node, (const xmlChar*)"uri", (const xmlChar*)new_uri.c_str ());
    account.unfetch (uri);
    account.fetch (new_uri);
    Ekiga::Runtime::run_in_main (boost::bind (&Opal::Account::presence_status_in_main, &account, new_uri, "unknown", ""));
  }

  // the first loop looks at groups we were in: are we still in?
  for (xmlNodePtr child = node->children ;
       child != NULL ;
       child = child->next) {

    if (child->type == XML_ELEMENT_NODE
        && child->name != NULL) {

      if (xmlStrEqual (BAD_CAST ("group"), child->name)) {

        xmlChar* xml_str = xmlNodeGetContent (child);

        if (xml_str != NULL) {
          if (std::find (new_groups.begin (), new_groups.end (), (const char*) xml_str) == new_groups.end ())
            nodes_to_remove.insert (child); // don't free what we loop on!
          xmlFree (xml_str);
        }
      }
    }
  }

  // ok, now we can clean up!
  for (std::set<xmlNodePtr>::iterator iter = nodes_to_remove.begin ();
       iter != nodes_to_remove.end ();
       ++iter) {

    xmlUnlinkNode (*iter);
    xmlFreeNode (*iter);
  }

  // the second loop looks for groups we weren't in but are now
  for (std::list<std::string>::const_iterator iter = new_groups.begin ();
       iter != new_groups.end ();
       iter++) {

    if (std::find (groups.begin (), groups.end (), *iter) == groups.end ())
      xmlNewChild (node, NULL,
                   BAD_CAST "group",
                   BAD_CAST robust_xmlEscape (node->doc, *iter).c_str ());
  }

  updated (this->shared_from_this ());
  trigger_saving ();

  return true;
}
TEST(logcat, get_size) {
    ASSERT_EQ(4, get_groups(
      "logcat -v brief -b radio -b events -b system -b main -g 2>/dev/null"));
}
Esempio n. 19
0
int main(int argc, char *argv[])
{
	int i;
	gid_t user_gid;
	uid_t user_uid;


	int is_only_group = 0;
	int is_only_group_all = 0;
	int is_name = 0;
	int is_only_user = 0;
	int is_real = 0;

	//bug!: myid -Gn - err
	char *opts="rgGnu";
	int opt, opt_c = 0;
	while((opt=getopt(argc,argv,opts))!=-1){
		switch(opt){
			case 'a':
				break;
			case 'g':
				is_only_group = 1;
				break;
			case 'G':
				is_only_group_all = 1;
				break;
			case 'n':
				is_name = 1;
				break;
			case 'r':
				is_real = 1;
				break;
			case 'u':
				is_only_user = 1;
				break;
		}
		opt_c++;
	}
	//without username
	if(argc == 1 || (opt_c + 1) == argc){
		if( is_real){
			user_gid = getgid();
			user_uid = getuid();
		}
		else{
			user_gid = getegid();
			user_uid = geteuid();

		}
	}
	//with username in command line
	else{
		user_gid = name_to_uid(argv[1+opt_c]);
		user_uid = name_to_gid(argv[1+opt_c]); 
	}
	// -g flag.
	if( is_only_group){
		if( is_name)
			printf("%s\n",gid_to_name(user_gid));
		else
			printf("%d\n",user_gid);
		return 0;
	}
	// -G flag.
	if( is_only_group_all){
		int list_size = 0;
		gid_t * user_groups = get_groups(gid_to_name(user_gid),&list_size);
		for( i=0;i<list_size;i++)
			if( is_name)
				printf("%s ",gid_to_name(user_groups[i]));
			else
				printf("%d ",user_groups[i]);
		printf("\n");
		return 0;
	}
	// -u flag.
	if( is_only_user){
		if( is_name)
			printf("%s\n",uid_to_name(user_uid));
		else
			printf("%d\n",user_uid);
		return 0;
	}
	//wrong flags
	if( is_name && is_real){
		fprintf(stderr,"id: cannot print only names or real IDs in default format\n");
		return EARG;
	}
	//common case:
	printf("uid=%d(%s) ",user_uid,uid_to_name(user_uid));
	printf("gid=%d(%s) ",user_gid,gid_to_name(user_gid));

	int list_size = 0;
	gid_t * user_groups = get_groups(gid_to_name(user_gid),&list_size);
	printf("groups=");
	printf("%s(%d)",gid_to_name(user_gid),user_gid);
	for( i=0;i<list_size;i++)
		printf("%d(%s) ",	user_groups[i],
					gid_to_name(user_groups[i]));
	printf("\n");
	return 0;
}
Esempio n. 20
0
groups* groups_get_x(pid_t pid,uid_t uid,gid_t gid,uint8_t lockmode) {
	double t;
	uint32_t h;
	groups *g,*gn,*gf;
	if (debug_mode) {
		fprintf(stderr,"groups_get(pid=%"PRIu32",uid=%"PRIu32",gid=%"PRIu32")\n",(uint32_t)pid,(uint32_t)uid,(uint32_t)gid);
	}
	zassert(pthread_mutex_lock(&glock));
	t = monotonic_seconds();
	h = HASHFN(pid,uid,gid);
//	fprintf(stderr,"groups_get hash: %"PRIu32"\n",h);
	for (gf = NULL,g = groups_hashtab[h] ; g!=NULL ; g = gn) {
		gn = g->next;
		if (g->time + to < t && lockmode==0 && g->locked==0 && g->lcnt==0) {
//			fprintf(stderr,"groups_get remove node (%"PRIu32",%"PRIu32",%"PRIu32") insert_time: %.3lf ; current_time: %.3lf ; timeout: %.3lf\n",g->pid,g->uid,g->gid,g->time,t,to);
			groups_remove(g);
		} else {
//			fprintf(stderr,"groups_get check node (%"PRIu32",%"PRIu32",%"PRIu32")\n",g->pid,g->uid,g->gid);
			if (g->pid==pid && g->uid==uid && g->gid==gid) {
				gf = g;
			}
		}
	}
	g = gf;
	if (g) {
		if (debug_mode) {
			fprintf(stderr,"groups_get(pid=%"PRIu32",uid=%"PRIu32",gid=%"PRIu32") - found data in cache\n",(uint32_t)pid,(uint32_t)uid,(uint32_t)gid);
		}
		g->lcnt++;
		if (lockmode==1) {
			g->locked = 1;
			if (debug_mode) {
				fprintf(stderr,"groups_get(pid=%"PRIu32",uid=%"PRIu32",gid=%"PRIu32") - lock cache\n",(uint32_t)pid,(uint32_t)uid,(uint32_t)gid);
			}
		}
		if (g->lcnt==1 && g->locked==0 && g->uid==0) { // refresh groups for user 'root' - only root can change groups
			if (debug_mode) {
				fprintf(stderr,"groups_get(pid=%"PRIu32",uid=%"PRIu32",gid=%"PRIu32") - refresh cache\n",(uint32_t)pid,(uint32_t)uid,(uint32_t)gid);
			}
			if (g->gidtab) {
				free(g->gidtab);
			}
			g->gidcnt = get_groups(pid,gid,&(g->gidtab));
		}
		if (lockmode==2) {
			g->locked = 0;
			if (debug_mode) {
				fprintf(stderr,"groups_get(pid=%"PRIu32",uid=%"PRIu32",gid=%"PRIu32") - unlock cache\n",(uint32_t)pid,(uint32_t)uid,(uint32_t)gid);
			}
		}
	} else {
		g = malloc(sizeof(groups));
		g->time = t;
		g->pid = pid;
		g->uid = uid;
		g->gid = gid;
		g->lcnt = 1;
		if (lockmode==1) { // emergency case
			if (debug_mode) {
				fprintf(stderr,"groups_get(pid=%"PRIu32",uid=%"PRIu32",gid=%"PRIu32") - emergency mode\n",(uint32_t)pid,(uint32_t)uid,(uint32_t)gid);
			}
			g->gidtab = malloc(sizeof(uint32_t));
			g->gidtab[0] = gid;
			g->gidcnt = 1;
			g->locked = 1;
		} else {
			g->gidcnt = get_groups(pid,gid,&(g->gidtab));
			g->locked = 0;
		}
		g->next = groups_hashtab[h];
		if (g->next) {
			g->next->prev = &(g->next);
		}
		g->prev = groups_hashtab+h;
		groups_hashtab[h] = g;
//		fprintf(stderr,"groups_get insert node (%"PRIu32",%"PRIu32",%"PRIu32")\n",g->pid,g->uid,g->gid);
	}
	zassert(pthread_mutex_unlock(&glock));
	if (debug_mode) {
		fprintf(stderr,"groups_get(pid=%"PRIu32",uid=%"PRIu32",gid=%"PRIu32"):",(uint32_t)pid,(uint32_t)uid,(uint32_t)gid);
		for (h=0 ; h<g->gidcnt ; h++) {
			fprintf(stderr,"%c%"PRIu32,(h==0)?'(':',',g->gidtab[h]);
		}
		if (g->gidcnt==0) {
			fprintf(stderr,"EMPTY\n");
		} else {
			fprintf(stderr,")\n");
		}
	}
	return g;
}
TEST(logcat, bad_buffer) {
    ASSERT_EQ(0, get_groups(
      "logcat -v brief -b radio,events,bogo,system,main -g 2>/dev/null"));
}
// duplicate test for get_size, but use comma-separated list of buffers
TEST(logcat, multiple_buffer) {
    ASSERT_EQ(4, get_groups(
      "logcat -v brief -b radio,events,system,main -g 2>/dev/null"));
}
Esempio n. 23
0
// get_user_info uses CURL calls to get the data for a user name and groups associated
// with a given opensso cookie
static int get_user_info(request_rec *r, const char *cookies, char ** user, char **groups) {
	CURL *curl_handle;
	CURLcode ec;
	curl_global_init(CURL_GLOBAL_ALL);
	curl_handle = curl_easy_init();
	long no_cert_flag = 0L;
	moon_svr_cfg* cfg = ap_get_module_config(r->server->module_config, &moon_module);

	if(curl_handle==NULL) {
		return HTTP_INTERNAL_SERVER_ERROR;
	}
	apr_file_t *groups_data;
	apr_file_t *user_data;
	apr_status_t rv;

	// opens the file/stream for writing data about user
	if(rv = open_file(r, &user_data, USER_TEMP_FILE_LOC) != OK) {
		curl_easy_cleanup(curl_handle);
		return rv;
	}
	// opens the file/stream for writing data about user groups
	if(rv = open_file(r, &groups_data, GROUPS_TEMP_FILE_LOC) != OK) {
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		return rv;
	}
	
	// set all options for curl call requesting user data
	rv = set_curl_options(curl_handle, (char*)cfg->user_data_url, &no_cert_flag, user_data,
									write_data, cookies);
	if(rv != OK) {
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return rv;
	}

	// execute request
	ec = curl_easy_perform(curl_handle);
	if(ec != CURLE_WRITE_ERROR && ec != CURLE_OK ) {	
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	double x = 0.0;
	curl_easy_getinfo(curl_handle,CURLINFO_TOTAL_TIME,&x);
	ap_rprintf(r,"\n\n<!--\nTime for user data request: %f\n-->\n\n",x);

	// set all options for curl call requesting groups data
	rv = set_curl_options(curl_handle, (char*)cfg->group_data_url, &no_cert_flag, groups_data, 					 				write_data, cookies);
	if(rv != OK) {
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return rv;
	}

	// execute request
	ec = curl_easy_perform(curl_handle);
	if(ec != CURLE_WRITE_ERROR && ec != CURLE_OK ) {	
		curl_easy_cleanup(curl_handle);
		apr_file_close(user_data);
		apr_file_close(groups_data);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	curl_easy_getinfo(curl_handle,CURLINFO_TOTAL_TIME,&x);
	ap_rprintf(r,"\n\n<!--\nTime for group data request: %f\n-->\n\n",x);

	// parse information from responses
	get_user(r, user_data, user);
	get_groups(r, groups_data, groups);

	// cleanup and return
	curl_easy_cleanup(curl_handle);
	apr_file_close(user_data);
	apr_file_close(groups_data);
	return OK;
}
Esempio n. 24
0
Node *Node::duplicate(bool p_use_instancing) const {


	Node *node=NULL;

	bool instanced=false;

	if (cast_to<InstancePlaceholder>()) {

		const InstancePlaceholder *ip = cast_to<const InstancePlaceholder>();
		InstancePlaceholder *nip = memnew( InstancePlaceholder );
		nip->set_instance_path( ip->get_instance_path() );
		node=nip;

	} else if (p_use_instancing && get_filename()!=String()) {

		Ref<PackedScene> res = ResourceLoader::load(get_filename());
		ERR_FAIL_COND_V(res.is_null(),NULL);
		node=res->instance();
		ERR_FAIL_COND_V(!node,NULL);

		instanced=true;

	} else {

		Object *obj = ObjectTypeDB::instance(get_type());
		ERR_FAIL_COND_V(!obj,NULL);
		node = obj->cast_to<Node>();
		if (!node)
			memdelete(obj);
		ERR_FAIL_COND_V(!node,NULL);
	}


	if (get_filename()!="") { //an instance
		node->set_filename(get_filename());
	}

	List<PropertyInfo> plist;

	get_property_list(&plist);

	for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {

		if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
			continue;
		String name = E->get().name;
		node->set( name, get(name) );

	}

	node->set_name(get_name());

	List<GroupInfo> gi;
	get_groups(&gi);
	for (List<GroupInfo>::Element *E=gi.front();E;E=E->next()) {

		node->add_to_group(E->get().name, E->get().persistent);
	}

	_duplicate_signals(this, node);

	for(int i=0;i<get_child_count();i++) {

		if (get_child(i)->data.parent_owned)
			continue;
		if (instanced && get_child(i)->data.owner==this)
			continue; //part of instance

		Node *dup = get_child(i)->duplicate(p_use_instancing);
		if (!dup) {

			memdelete(node);
			return NULL;
		}

		node->add_child(dup);
	}

	return node;
}
Esempio n. 25
0
/*
 * increment_gids
 *
 * It increments the members of the `qg'->gid array until all its
 * gids point to gnodes present in the ext_map, which don't have
 * a particular gnode->flag or node->flag set.
 *
 * In order to verify that a gnode doesn't have the flag set the
 * `is_gnode_flag_set' function is called, the same is done for the nodes with
 * the `is_node_flag_set' function.
 * `is_gnode_flag_set' returns 1 if the flag is set.
 *
 * increment_gids() starts from the qg->gid[`level'] member and finishes to
 * qg->gid[qg->levels-1].
 * If all the gids point to gnodes, which have the gnode->flag set, -1 is
 * returned.
 * It's assumed that `ext_map' and `int_map' are the maps relative to the
 * `qg' quadro_group.
 */
int
increment_gids(quadro_group * qg, int level, map_gnode ** ext_map,
			   map_node * int_map,
			   int (*is_gnode_flag_set) (map_gnode * gnode),
			   int (*is_node_flag_set) (map_node * node))
{
	int g, groups, gid, i, e = 0, family;

	if (level >= qg->levels)
		return -1;

	family = qg->ipstart[level].family;

	g = level == qg->levels ? 0 : qg->gid[level];
	groups = get_groups(qg->levels, level);
	gid = qg->gid[level];

	if ((!level && !is_node_flag_set(&int_map[gid])) ||
		(level && is_gnode_flag_set(&ext_map[_EL(level)][g]))) {

		/*
		 * find a gid in this `level' which isn't full
		 */
		for (i = 0, e = 0; i < groups; i++) {
			qg->gid[level] = (gid + i) % groups;

			if (is_group_invalid(qg->gid, qg->gid[level], level, family))
				continue;

			if ((!level && is_node_flag_set(&int_map[qg->gid[level]])) ||
				(level
				 &&
				 !is_gnode_flag_set(&ext_map[_EL(level)][qg->gid[level]])))
			{
				e = 1;
				break;
			}
		}

		/*
		 * not a single free gid was found
		 */
		if (!e) {
			g = level + 1 == qg->levels ? 0 : qg->gid[level + 1];

			if ((is_gmap_full_flag_set == is_gnode_flag_set) &&
				!(ext_map[_EL(level + 1)][g].flags & GMAP_FULL)) {
				/*
				 * There is a logical contradiction here:
				 * we didn't find any free (g)nodes in this
				 * level, but the upper gnode at level+1,
				 * which is the parent of this level, isn't
				 * marked as full! So what's happening here?
				 * Ignore this absurd and mark it as full -_-
				 */
				ext_map[_EL(level + 1)][g].flags |= GMAP_FULL;
				debug(DBG_NORMAL, ERROR_MSG "logical "
					  "contradiction detected", ERROR_POS);
			}

			/*
			 * Recurse by leveling up
			 */
			if (!increment_gids(qg, level + 1, ext_map, int_map,
								is_gnode_flag_set, is_node_flag_set))
				/*
				 * We changed one of our upper gid, we can
				 * retake the old gid we had at this `level'
				 */
				qg->gid[level] = gid;
			else
				/*
				 * It's all full!
				 */
				return -1;
		}
	}

	return 0;
}
Esempio n. 26
0
void
Opal::Presentity::add_actions ()
{
  /* Pull actions */
  boost::shared_ptr<Ekiga::PresenceCore> pcore = presence_core.lock ();
  if (pcore)
    pcore->pull_actions (*this, get_name (), get_uri ());

  add_action (Ekiga::ActionPtr (new Ekiga::Action ("edit", _("_Edit"),
                                                   boost::bind (&Opal::Presentity::edit_presentity, this))));
  add_action (Ekiga::ActionPtr (new Ekiga::Action ("remove", _("_Remove"),
                                                   boost::bind (&Opal::Presentity::remove, this))));
  add_action (Ekiga::ActionPtr (new Ekiga::Action ("rename", _("Rename _Groups"),
                                                   boost::bind (&Opal::Account::on_rename_group,
                                                                (Opal::Account *) &account, get_groups ()))));
}
Esempio n. 27
0
/*
 * process_flags - perform command line argument setting
 *
 *	process_flags() interprets the command line arguments and sets the
 *	values that the user will be created with accordingly. The values
 *	are checked for sanity.
 */
static void process_flags (int argc, char **argv)
{
	const struct group *grp;
	const struct passwd *pwd;

	const struct spwd *spwd = NULL;
	int anyflag = 0;
	int arg;

	if (argc == 1 || argv[argc - 1][0] == '-')
		usage ();

	if (!(pwd = getpwnam (argv[argc - 1]))) {
		fprintf (stderr, _("%s: user %s does not exist\n"),
			 Prog, argv[argc - 1]);
		exit (E_NOTFOUND);
	}

	user_name = argv[argc - 1];
	user_id = pwd->pw_uid;
	user_gid = pwd->pw_gid;
	user_comment = xstrdup (pwd->pw_gecos);
	user_home = xstrdup (pwd->pw_dir);
	user_shell = xstrdup (pwd->pw_shell);
#ifdef WITH_AUDIT
	user_newname = user_name;
	user_newid = user_id;
	user_newgid = user_gid;
	user_newcomment = user_comment;
	user_newhome = user_home;
	user_newshell = user_shell;
#endif

#ifdef	USE_NIS
	/*
	 * Now make sure it isn't an NIS user.
	 */
	if (__ispwNIS ()) {
		char *nis_domain;
		char *nis_master;

		fprintf (stderr, _("%s: user %s is a NIS user\n"),
			 Prog, user_name);

		if (!yp_get_default_domain (&nis_domain) &&
		    !yp_master (nis_domain, "passwd.byname", &nis_master)) {
			fprintf (stderr, _("%s: %s is the NIS master\n"),
				 Prog, nis_master);
		}
		exit (E_NOTFOUND);
	}
#endif

	if (is_shadow_pwd && (spwd = getspnam (user_name))) {
		user_expire = spwd->sp_expire;
		user_inactive = spwd->sp_inact;
#ifdef WITH_AUDIT
		user_newexpire = user_expire;
		user_newinactive = user_inactive;
#endif
	}

	{
		/*
		 * Parse the command line options.
		 */
		int c;
		static struct option long_options[] = {
			{"append", required_argument, NULL, 'a'},
			{"comment", required_argument, NULL, 'c'},
			{"home", required_argument, NULL, 'd'},
			{"expiredate", required_argument, NULL, 'e'},
			{"inactive", required_argument, NULL, 'f'},
			{"gid", required_argument, NULL, 'g'},
			{"groups", required_argument, NULL, 'G'},
			{"help", no_argument, NULL, 'h'},
			{"login", required_argument, NULL, 'l'},
			{"lock", no_argument, NULL, 'L'},
			{"move-home", no_argument, NULL, 'm'},
			{"non-unique", no_argument, NULL, 'o'},
			{"password", required_argument, NULL, 'p'},
			{"shell", required_argument, NULL, 's'},
			{"uid", required_argument, NULL, 'u'},
			{"unlock", no_argument, NULL, 'U'},
			{NULL, 0, NULL, '\0'}
		};
		while ((c =
			getopt_long (argc, argv, "ac:d:e:f:g:G:l:Lmop:s:u:U",
				     long_options, NULL)) != -1) {
			switch (c) {
			case 'a':
				aflg++;
				break;
			case 'c':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
#ifdef WITH_AUDIT
				user_newcomment = optarg;
#else
				user_comment = optarg;
#endif
				cflg++;
				break;
			case 'd':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
				dflg++;
				user_newhome = optarg;
				break;
			case 'e':
				if (*optarg) {
#ifdef WITH_AUDIT
					user_newexpire = strtoday (optarg);
					if (user_newexpire == -1) {
#else
					user_expire = strtoday (optarg);
					if (user_expire == -1) {
#endif
						fprintf (stderr,
							 _
							 ("%s: invalid date `%s'\n"),
							 Prog, optarg);
						exit (E_BAD_ARG);
					}
#ifdef WITH_AUDIT
					user_newexpire *= DAY / SCALE;
#else
					user_expire *= DAY / SCALE;
#endif
				} else
#ifdef WITH_AUDIT
					user_newexpire = -1;
#else
					user_expire = -1;
#endif
				eflg++;
				break;
			case 'f':
#ifdef WITH_AUDIT
				user_newinactive = get_number (optarg);
#else
				user_inactive = get_number (optarg);
#endif
				fflg++;
				break;
			case 'g':
				grp = getgr_nam_gid (optarg);
				if (!grp) {
					fprintf (stderr,
						 _("%s: unknown group %s\n"),
						 Prog, optarg);
					exit (E_NOTFOUND);
				}
				user_newgid = grp->gr_gid;
				gflg++;
				break;
			case 'G':
				if (get_groups (optarg))
					exit (E_NOTFOUND);
				Gflg++;
				break;
			case 'l':
				if (!check_user_name (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}

				/*
				 * If the name does not really change, we mustn't
				 * set the flag as this will cause rather serious
				 * problems later!
				 */
				if (strcmp (user_name, optarg))
					lflg++;

				user_newname = optarg;
				break;
			case 'L':
				if (Uflg || pflg)
					usage ();

				Lflg++;
				break;
			case 'm':
				if (!dflg)
					usage ();

				mflg++;
				break;
			case 'o':
				if (!uflg)
					usage ();

				oflg++;
				break;
			case 'p':
				if (Lflg || Uflg)
					usage ();

				user_pass = optarg;
				pflg++;
				break;
			case 's':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
#ifdef WITH_AUDIT
				user_newshell = optarg;
#else
				user_shell = optarg;
#endif
				sflg++;
				break;
			case 'u':
				user_newid = get_id (optarg);
				uflg++;
				break;
			case 'U':
				if (Lflg && pflg)
					usage ();

				Uflg++;
				break;
			default:
				usage ();
			}
			anyflag++;
		}
	}

	if (anyflag == 0) {
		fprintf (stderr, _("%s: no flags given\n"), Prog);
		exit (E_USAGE);
	}
	if (!is_shadow_pwd && (eflg || fflg)) {
		fprintf (stderr,
			 _
			 ("%s: shadow passwords required for -e and -f\n"),
			 Prog);
		exit (E_USAGE);
	}

	if (optind != argc - 1)
		usage ();

	if (aflg && (!Gflg)) {
		fprintf (stderr,
			 _("%s: -a flag is ONLY allowed with the -G flag\n"),
			 Prog);
		usage ();
		exit (E_USAGE);
	}

	if (dflg && strcmp (user_home, user_newhome) == 0)
		dflg = mflg = 0;

	if (uflg && user_id == user_newid)
		uflg = oflg = 0;

	if (lflg && getpwnam (user_newname)) {
		fprintf (stderr, _("%s: user %s exists\n"), Prog, user_newname);
		exit (E_NAME_IN_USE);
	}

	if (uflg && !oflg && getpwuid (user_newid)) {
		fprintf (stderr, _("%s: uid %lu is not unique\n"),
			 Prog, (unsigned long) user_newid);
		exit (E_UID_IN_USE);
	}
}

/*
 * close_files - close all of the files that were opened
 *
 *	close_files() closes all of the files that were opened for this new
 *	user. This causes any modified entries to be written out.
 */
static void close_files (void)
{
	if (!pw_close ()) {
		fprintf (stderr, _("%s: cannot rewrite password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_close ()) {
		fprintf (stderr,
			 _("%s: cannot rewrite shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd)
		spw_unlock ();
	(void) pw_unlock ();

	/*
	 * Close the DBM and/or flat files
	 */
	endpwent ();
	endspent ();
	endgrent ();
#ifdef	SHADOWGRP
	endsgent ();
#endif
}

/*
 * open_files - lock and open the password files
 *
 *	open_files() opens the two password files.
 */
static void open_files (void)
{
	if (!pw_lock ()) {
		fprintf (stderr, _("%s: unable to lock password file\n"), Prog);
		exit (E_PW_UPDATE);
	}
	if (!pw_open (O_RDWR)) {
		fprintf (stderr, _("%s: unable to open password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_lock ()) {
		fprintf (stderr,
			 _("%s: cannot lock shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_open (O_RDWR)) {
		fprintf (stderr,
			 _("%s: cannot open shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
}

/*
 * usr_update - create the user entries
 *
 *	usr_update() creates the password file entries for this user and
 *	will update the group entries if required.
 */
static void usr_update (void)
{
	struct passwd pwent;
	const struct passwd *pwd;

	struct spwd spent;
	const struct spwd *spwd = NULL;

	/*
	 * Locate the entry in /etc/passwd, which MUST exist.
	 */
	pwd = pw_locate (user_name);
	if (!pwd) {
		fprintf (stderr, _("%s: %s not found in /etc/passwd\n"),
			 Prog, user_name);
		fail_exit (E_NOTFOUND);
	}
	pwent = *pwd;
	new_pwent (&pwent);


	/* 
	 * Locate the entry in /etc/shadow. It doesn't have to exist, and
	 * won't be created if it doesn't.
	 */
	if (is_shadow_pwd && (spwd = spw_locate (user_name))) {
		spent = *spwd;
		new_spent (&spent);
	}

	if (lflg || uflg || gflg || cflg || dflg || sflg || pflg
	    || Lflg || Uflg) {
		if (!pw_update (&pwent)) {
			fprintf (stderr,
				 _("%s: error changing password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
		if (lflg && !pw_remove (user_name)) {
			fprintf (stderr,
				 _("%s: error removing password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
	}
	if (spwd && (lflg || eflg || fflg || pflg || Lflg || Uflg)) {
		if (!spw_update (&spent)) {
			fprintf (stderr,
				 _
				 ("%s: error adding new shadow password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
		if (lflg && !spw_remove (user_name)) {
			fprintf (stderr,
				 _
				 ("%s: error removing shadow password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
	}
}

/*
 * move_home - move the user's home directory
 *
 *	move_home() moves the user's home directory to a new location. The
 *	files will be copied if the directory cannot simply be renamed.
 */
static void move_home (void)
{
	struct stat sb;

	if (mflg && stat (user_home, &sb) == 0) {
		/*
		 * Don't try to move it if it is not a directory
		 * (but /dev/null for example).  --marekm
		 */
		if (!S_ISDIR (sb.st_mode))
			return;

		if (access (user_newhome, F_OK) == 0) {
			fprintf (stderr, _("%s: directory %s exists\n"),
				 Prog, user_newhome);
			fail_exit (E_HOMEDIR);
		} else if (rename (user_home, user_newhome)) {
			if (errno == EXDEV) {
				if (mkdir (user_newhome, sb.st_mode & 0777)) {
					fprintf (stderr,
						 _
						 ("%s: can't create %s\n"),
						 Prog, user_newhome);
				}
				if (chown (user_newhome, sb.st_uid, sb.st_gid)) {
					fprintf (stderr,
						 _("%s: can't chown %s\n"),
						 Prog, user_newhome);
					rmdir (user_newhome);
					fail_exit (E_HOMEDIR);
				}
				if (copy_tree (user_home, user_newhome,
					       uflg ? user_newid : -1,
					       gflg ? user_newgid : -1) == 0) {
					if (remove_tree (user_home) != 0 ||
					    rmdir (user_home) != 0)
						fprintf (stderr,
							 _
							 ("%s: warning: failed to completely remove old home directory %s"),
							 Prog, user_home);
#ifdef WITH_AUDIT
					audit_logger (AUDIT_USER_CHAUTHTOK,
						      Prog,
						      "moving home directory",
						      user_newname, user_newid,
						      1);
#endif
					return;
				}

				(void) remove_tree (user_newhome);
				(void) rmdir (user_newhome);
			}
			fprintf (stderr,
				 _
				 ("%s: cannot rename directory %s to %s\n"),
				 Prog, user_home, user_newhome);
			fail_exit (E_HOMEDIR);
		}
#ifdef WITH_AUDIT
		audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			      "moving home directory", user_newname, user_newid,
			      1);
#endif
	}
	if (uflg || gflg) {
#ifdef WITH_AUDIT
		audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			      "changing home directory owner", user_newname,
			      user_newid, 1);
#endif
		chown (dflg ? user_newhome : user_home,
		       uflg ? user_newid : user_id,
		       gflg ? user_newgid : user_gid);
	}
}

/*
 * update_files - update the lastlog and faillog files
 */
static void update_files (void)
{
	struct lastlog ll;
	struct faillog fl;
	int fd;

	/*
	 * Relocate the "lastlog" entries for the user. The old entry is
	 * left alone in case the UID was shared. It doesn't hurt anything
	 * to just leave it be.
	 */
	if ((fd = open (LASTLOG_FILE, O_RDWR)) != -1) {
		lseek (fd, (off_t) user_id * sizeof ll, SEEK_SET);
		if (read (fd, (char *) &ll, sizeof ll) == sizeof ll) {
			lseek (fd, (off_t) user_newid * sizeof ll, SEEK_SET);
			write (fd, (char *) &ll, sizeof ll);
		}
		close (fd);
	}

	/*
	 * Relocate the "faillog" entries in the same manner.
	 */
	if ((fd = open (FAILLOG_FILE, O_RDWR)) != -1) {
		lseek (fd, (off_t) user_id * sizeof fl, SEEK_SET);
		if (read (fd, (char *) &fl, sizeof fl) == sizeof fl) {
			lseek (fd, (off_t) user_newid * sizeof fl, SEEK_SET);
			write (fd, (char *) &fl, sizeof fl);
		}
		close (fd);
	}
}

#ifndef NO_MOVE_MAILBOX
/*
 * This is the new and improved code to carefully chown/rename the user's
 * mailbox. Maybe I am too paranoid but the mail spool dir sometimes
 * happens to be mode 1777 (this makes mail user agents work without
 * being setgid mail, but is NOT recommended; they all should be fixed
 * to use movemail).  --marekm
 */
static void move_mailbox (void)
{
	const char *maildir;
	char mailfile[1024], newmailfile[1024];
	int fd;
	struct stat st;

	maildir = getdef_str ("MAIL_DIR");
#ifdef MAIL_SPOOL_DIR
	if (!maildir && !getdef_str ("MAIL_FILE"))
		maildir = MAIL_SPOOL_DIR;
#endif
	if (!maildir)
		return;

	/*
	 * O_NONBLOCK is to make sure open won't hang on mandatory locks.
	 * We do fstat/fchown to make sure there are no races (someone
	 * replacing /var/spool/mail/luser with a hard link to /etc/passwd
	 * between stat and chown).  --marekm
	 */
	snprintf (mailfile, sizeof mailfile, "%s/%s", maildir, user_name);
	fd = open (mailfile, O_RDONLY | O_NONBLOCK, 0);
	if (fd < 0) {
		/* no need for warnings if the mailbox doesn't exist */
		if (errno != ENOENT)
			perror (mailfile);
		return;
	}
	if (fstat (fd, &st) < 0) {
		perror ("fstat");
		close (fd);
		return;
	}
	if (st.st_uid != user_id) {
		/* better leave it alone */
		fprintf (stderr, _("%s: warning: %s not owned by %s\n"),
			 Prog, mailfile, user_name);
		close (fd);
		return;
	}
	if (uflg) {
		if (fchown (fd, user_newid, (gid_t) - 1) < 0) {
			perror (_("failed to change mailbox owner"));
		}
#ifdef WITH_AUDIT
		else {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
				      "changing mail file owner", user_newname,
				      user_newid, 1);
		}
#endif
	}

	close (fd);

	if (lflg) {
		snprintf (newmailfile, sizeof newmailfile, "%s/%s",
			  maildir, user_newname);
		if (link (mailfile, newmailfile) || unlink (mailfile)) {
			perror (_("failed to rename mailbox"));
		}
#ifdef WITH_AUDIT
		else {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
				      "changing mail file name", user_newname,
				      user_newid, 1);
		}
#endif
	}
}
#endif

/*
 * main - usermod command
 */
int main (int argc, char **argv)
{
	int grp_err = 0;

#ifdef USE_PAM
	pam_handle_t *pamh = NULL;
	struct passwd *pampw;
	int retval;
#endif

#ifdef WITH_AUDIT
	audit_help_open ();
#endif

	/*
	 * Get my name so that I can use it to report errors.
	 */
	Prog = Basename (argv[0]);

	setlocale (LC_ALL, "");
	bindtextdomain (PACKAGE, LOCALEDIR);
	textdomain (PACKAGE);

	sys_ngroups = sysconf (_SC_NGROUPS_MAX);
	user_groups = malloc ((1 + sys_ngroups) * sizeof (char *));
	user_groups[0] = (char *) 0;

	OPENLOG ("usermod");

	is_shadow_pwd = spw_file_present ();
#ifdef SHADOWGRP
	is_shadow_grp = sgr_file_present ();
#endif

	process_flags (argc, argv);

#ifdef USE_PAM
	retval = PAM_SUCCESS;

	pampw = getpwuid (getuid ());
	if (pampw == NULL) {
		retval = PAM_USER_UNKNOWN;
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_start ("usermod", pampw->pw_name, &conv, &pamh);
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_authenticate (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_acct_mgmt (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval != PAM_SUCCESS) {
		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
		exit (1);
	}
#endif				/* USE_PAM */

	/*
	 * Do the hard stuff - open the files, change the user entries,
	 * change the home directory, then close and update the files.
	 */
	open_files ();

	usr_update ();
	nscd_flush_cache ("passwd");
	nscd_flush_cache ("group");

	close_files ();

	if (Gflg || lflg)
		grp_err = grp_update ();

	if (mflg)
		move_home ();

#ifndef NO_MOVE_MAILBOX
	if (lflg || uflg)
		move_mailbox ();
#endif

	if (uflg) {
		update_files ();

		/*
		 * Change the UID on all of the files owned by `user_id' to
		 * `user_newid' in the user's home directory.
		 */
		chown_tree (dflg ? user_newhome : user_home,
			    user_id, user_newid,
			    user_gid, gflg ? user_newgid : user_gid);
	}

	if (grp_err)
		exit (E_GRP_UPDATE);

#ifdef USE_PAM
	if (retval == PAM_SUCCESS)
		pam_end (pamh, PAM_SUCCESS);
#endif				/* USE_PAM */

	exit (E_SUCCESS);
	/* NOT REACHED */
}