summaryrefslogtreecommitdiff
path: root/members_src/members.cc
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2016-06-16 21:06:38 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2016-06-16 21:06:38 +0200
commit7627939253a431578e79cb0d157d552f15d802a1 (patch)
tree9488ee68ee4a5a827e0225a191e44396cc098138 /members_src/members.cc
downloadoc-pam-7627939253a431578e79cb0d157d552f15d802a1.tar.gz
oc-pam-7627939253a431578e79cb0d157d552f15d802a1.zip
hack together a working versionHEADmaster
Diffstat (limited to 'members_src/members.cc')
-rw-r--r--members_src/members.cc510
1 files changed, 510 insertions, 0 deletions
diff --git a/members_src/members.cc b/members_src/members.cc
new file mode 100644
index 0000000..a2d0532
--- /dev/null
+++ b/members_src/members.cc
@@ -0,0 +1,510 @@
+// members is the complement of groups: whereas groups shows the groups a
+// specified user belongs to, members shows users belonging to a specified
+// group.
+
+// PRESENTLY WORKING ON FULL OPTION PARSING (search for /**/ for work pt)
+
+// Copyright (c) 1997 by Jim Lynch.
+// This software comes with NO WARRANTY WHATSOEVER.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 dated June, 1991, or, at your
+// option, any LATER version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// On Debian Linux systems, the complete text of the GNU General
+// Public License can be found in `/usr/doc/copyright/GPL' (on some
+// installations) or /usr/share/common-licenses/GPL (on newer
+// ones).
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cstdio>
+#include <iostream>
+
+ using std::cerr;
+ using std::ostream;
+ using std::endl;
+ using std::cout;
+ using std::hex;
+ using std::endl;
+
+#include <grp.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <getopt.h>
+
+#define ALL_OPT 'a'
+#define PRIMARY_OPT 'p'
+#define SECONDARY_OPT 's'
+#define TWO_LINES_OPT 't'
+#define HELP_OPT 'h'
+
+#define END_SHORT_OPT '\0'
+#define END_LONG_OPT {(char *) 0, 0, (int *) 0, '\0'}
+
+const char short_blank = END_SHORT_OPT;
+const struct option long_blank = END_LONG_OPT;
+
+struct option longopts[] =
+{
+ {"all", no_argument, (int *) 0, ALL_OPT },
+ {"primary", no_argument, (int *) 0, PRIMARY_OPT },
+ {"secondary", no_argument, (int *) 0, SECONDARY_OPT },
+ {"two-lines", no_argument, (int *) 0, TWO_LINES_OPT },
+ {"help", no_argument, (int *) 0, HELP_OPT },
+ END_LONG_OPT
+};
+
+char opt_string[] =
+{
+ ALL_OPT,
+ PRIMARY_OPT,
+ SECONDARY_OPT,
+ TWO_LINES_OPT,
+ HELP_OPT,
+ END_SHORT_OPT
+};
+
+int optionlen(struct option *option_array)
+{
+ int result = 0;
+
+ while(option_array[result].name != NULL)
+ result++;
+
+ return result;
+}
+
+void remove_short_option(char option, char *option_array)
+{
+ int i;
+ int found_index = -1; /* index of found index !or! -1 if none */
+ int size = strlen(option_array);
+
+ for(i = 0; i < size; i++)
+ {
+ if(option_array[i] == option)
+ {
+ found_index = i;
+ break;
+ }
+ }
+
+ if(found_index != -1)
+ {
+ if(found_index != size - 1) /* not last item? */
+ {
+ /* replace found item with last item */
+
+ option_array[found_index] = option_array[size - 1];
+ }
+
+ /* blank out last item */
+ option_array[size - 1] = short_blank;
+ }
+}
+
+void remove_long_option(char option, struct option *option_array)
+{
+ int i;
+ int found_index = -1; /* index of found index !or! -1 if none */
+ int size = optionlen(option_array);
+
+ for(i = 0; i < size; i++)
+ {
+ if(option_array[i].val == option)
+ {
+ found_index = i;
+ break;
+ }
+ }
+
+ if(found_index != -1)
+ {
+ if(found_index != size - 1) /* not last item? */
+ {
+ /* replace found item with last item */
+
+ option_array[found_index] = option_array[size - 1];
+ }
+
+ /* blank out last item */
+ option_array[size - 1] = long_blank;
+ }
+}
+
+void print_option_array(struct option *option_array)
+{
+ int i = 0;
+
+ while(option_array[i].val != short_blank)
+ {
+ if(option_array[i].flag != NULL)
+ {
+ cout
+ << "{"
+ << option_array[i].name << ", "
+ << option_array[i].has_arg << ", "
+ << (*option_array[i].flag) << ", '"
+ << ( (char) option_array[i].val ) << "'=0x"
+ << std::hex << option_array[i].val << "}" << std::dec << endl;
+ }
+ else
+ {
+ cout
+ << "{"
+ << option_array[i].name << ", "
+ << option_array[i].has_arg << ", NULL, '"
+ << ( (char) option_array[i].val ) << "'=0x"
+ << std::hex << option_array[i].val << "}" << std::dec << endl;
+ }
+
+ i++;
+ }
+}
+
+void disable_option(char *opt_chars)
+{
+ while(*opt_chars)
+ {
+ remove_short_option(*opt_chars, opt_string);
+ remove_long_option(*opt_chars, longopts);
+
+ opt_chars++;
+ }
+}
+
+void usage(ostream &out, char *name)
+{
+ out << endl << "Usage: " << name;
+ out << " [ -apst --all --primary --secondary --two-lines ] <group>" << endl;
+}
+
+//receives:
+// - C string containing group name
+// - pointer to int containing (!assumed initialized!) flag
+// indicating whether a member name was printed on this line.
+// (if true, at least one member had been printed)
+// returns true if group found.
+
+int display_primaries(const char *groupString, int *printedOne)
+{
+ int result = 0;
+ struct group *theGroup;
+
+ theGroup = getgrnam(groupString);
+
+ if(theGroup)
+ {
+ struct passwd *thePasswd;
+
+ setpwent();
+
+ thePasswd = getpwent();
+
+ if(thePasswd)
+ {
+ thePasswd = getpwent();
+
+ while(thePasswd)
+ {
+ if(thePasswd->pw_gid == theGroup->gr_gid)
+ {
+ // if there is at least one, print it without any space
+ // if there is at least one more, print space then it
+
+ if(*printedOne)
+ cout << " ";
+ else
+ *printedOne = 1;
+
+ cout << thePasswd->pw_name;
+ }
+
+ thePasswd = getpwent();
+ }
+ }
+
+ endpwent();
+
+ result = 1;
+ }
+
+ return result;
+}
+
+//receives:
+// - C string containing group name
+// - pointer to int containing (!assumed initialized!) flag
+// indicating whether a member name was printed on this line.
+// (if true, at least one member had been printed)
+// returns true if group found.
+
+int display_secondaries(const char *groupString, int *printedOne)
+{
+ int result = 0;
+ struct group *theGroup;
+
+ theGroup = getgrnam(groupString);
+
+ if(theGroup)
+ {
+ char **member = theGroup->gr_mem;
+
+ result = 1;
+
+ // if there is at least one, print it without any space
+ // if there is at least one more, print space then it
+
+ while(*member)
+ {
+ if(*printedOne)
+ cout << " ";
+ else
+ *printedOne = 1;
+
+ cout << *member++;
+ }
+ }
+
+ return result;
+}
+
+int main(int argc, char *argv[])
+{
+ int result = 1; // pessimistic since we do something if success
+ int first_nonopt = 1; /* index of the first non-option in argv */
+ int is_bad_opt = 0; /* true if unrecognized option */
+ int getopt_result;
+ int longindex = 0;
+
+ int wants_help = 0; /* boolean from options */
+ int wants_all_members = 0;
+ int wants_primary = 0;
+ int wants_secondary = 0;
+ int wants_two_lines = 0;
+
+ getopt_result =
+ getopt_long
+ (
+ argc,
+ argv,
+ opt_string,
+ longopts,
+ &longindex
+ );
+
+ while(getopt_result != EOF)
+ {
+ /* process opts here */
+
+ switch(getopt_result)
+ {
+ case ALL_OPT:
+ wants_all_members = 1;
+
+ disable_option("apst");
+
+ break;
+
+ case PRIMARY_OPT:
+ wants_primary = 1;
+
+ disable_option("apst");
+
+ break;
+
+ case SECONDARY_OPT:
+ wants_secondary = 1;
+
+ disable_option("apst");
+
+ break;
+
+ case TWO_LINES_OPT:
+ wants_two_lines = 1;
+
+ disable_option("apst");
+
+ break;
+
+ case HELP_OPT:
+ wants_help = 1;
+
+ disable_option("apst");
+
+ break;
+
+ case '?':
+ default:
+ is_bad_opt = 1;
+ break;
+ }
+
+ if(is_bad_opt)
+ break;
+ else
+ getopt_result =
+ getopt_long
+ (
+ argc,
+ argv,
+ opt_string,
+ longopts,
+ &longindex
+ );
+ }
+
+ first_nonopt = optind;
+
+#ifdef SKIP
+ // display results of option parsing
+ cout << "wants_help: " << ( wants_help ? "yes" : "no" ) << endl;
+ cout << "wants_all_members: " << ( wants_all_members ? "yes" : "no" ) << endl;
+ cout << "wants_primary: " << ( wants_primary ? "yes" : "no" ) << endl;
+ cout << "wants_secondary: " << ( wants_secondary ? "yes" : "no" ) << endl;
+ cout << "wants_two_lines: " << ( wants_two_lines ? "yes" : "no" ) << endl;
+ cout << "argc: " << argc << "; first_nonopt: " << first_nonopt << endl;
+#endif
+
+ if(wants_help)
+ {
+ usage(cout, argv[0]);
+
+ cout << "You can use -one- of -a, -p, -s, or -t." << endl;
+
+ cout << endl;
+ cout << endl;
+ cout << "OPTIONS" << endl;
+ cout << endl;
+ cout << " -a or --all" << endl;
+ cout << " [default] show all members, both primary and secondary." << endl;
+ cout << endl;
+ cout << " -p or --primary" << endl;
+ cout << " show only primary members" << endl;
+ cout << " -s or --secondary" << endl;
+ cout << " show only secondary members" << endl;
+ cout << "" << endl;
+ cout << " -t or --two-lines" << endl;
+ cout << " output two lines, first is primary group members," << endl;
+ cout << " secondary members on the second line." << endl;
+ cout << "" << endl;
+ cout << " -h or --help" << endl;
+ cout << " print this message and exit successfully" << endl;
+ cout << "" << endl;
+ cout << "ARGUMENTS" << endl;
+ cout << "" << endl;
+ cout << " group (required)" << endl;
+ cout << " the group to find members in." << endl;
+ cout << "" << endl;
+ cout << "SEE ALSO: man members for details." << endl;
+ cout << "" << endl;
+
+ return 0;
+ }
+ else if(argc != first_nonopt + 1)
+ {
+ usage(cerr, argv[0]);
+
+ return 1;
+ }
+
+ if(argc == first_nonopt + 1)
+ {
+ int bad = 0;
+ int sbad = 0;
+ int printedOne;
+
+ if // user wants default (i.e., no option selected)?
+ (
+ !
+ (
+ wants_all_members ||
+ wants_primary ||
+ wants_secondary ||
+ wants_two_lines
+ )
+ )
+ {
+ wants_all_members = 1; // the default for this app
+ }
+
+ // fill in responses to errors
+
+ if(wants_all_members)
+ {
+ printedOne = 0;
+
+ if(display_primaries(argv[first_nonopt], &printedOne))
+ {
+ if(display_secondaries(argv[first_nonopt], &printedOne))
+ if(printedOne)
+ cout << endl;
+ else
+ sbad = 1;
+ }
+ else
+ bad = 1;
+ }
+ else if(wants_primary)
+ {
+ printedOne = 0;
+
+ bad = ! display_primaries(argv[first_nonopt], &printedOne);
+
+ if(! bad)
+ cout << endl;
+ }
+ else if(wants_secondary)
+ {
+ printedOne = 0;
+
+ bad = ! display_secondaries(argv[first_nonopt], &printedOne);
+
+ if( (! bad) && printedOne)
+ cout << endl;
+ }
+ else if(wants_two_lines)
+ {
+ printedOne = 0;
+
+ bad = ! display_primaries(argv[first_nonopt], &printedOne);
+
+ if(! bad)
+ {
+ cout << endl;
+
+ printedOne = 0;
+
+ sbad = ! display_secondaries(argv[first_nonopt], &printedOne);
+
+ cout << endl;
+ }
+ }
+
+ if(bad) // presumably, group does not exist
+ {
+ cerr << "members: group " << argv[first_nonopt] << " does not exist";
+ cerr << endl;
+ }
+
+ result = bad || sbad;
+ }
+ else
+ result = 1;
+
+ return result;
+}
+