File: 04_use_array_for_getgrent.dpatch

package info (click to toggle)
libnss-pgsql 1.4.0debian-3
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 1,596 kB
  • ctags: 137
  • sloc: sh: 9,625; ansic: 983; xml: 392; makefile: 70; sql: 38
file content (140 lines) | stat: -rw-r--r-- 4,471 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#! /bin/sh /usr/share/dpatch/dpatch-run
## 04_use_array_for_getgrent.dpatch by Stephen Gran <sgran@debian.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Use a single lookup for all groups, instead of one to seed the 
## DP: list and one for each group found.

@DPATCH@
--- a/src/backend.c	2007-09-02 21:55:33.000000000 -0400
+++ b/src/backend.c	2007-09-02 22:14:39.000000000 -0400
@@ -23,6 +23,7 @@
 #define GROUP_NAME   0
 #define GROUP_PASSWD 1
 #define GROUP_GID    2
+#define GROUP_MEM    3
 /* define passwd column names */
 #define PASSWD_NAME   0
 #define PASSWD_PASSWD 1
@@ -218,6 +219,85 @@
 	return NSS_STATUS_SUCCESS;
 }
 
+enum nss_status
+copy_attr_grouparray(char *sptr,
+                                  char **valptr, char **buffer, size_t *buflen, int *errnop)
+{
+	size_t slen;
+	
+	slen = strlen(sptr);
+	if(*buflen < slen+1) {
+		*errnop = ERANGE;
+		return NSS_STATUS_TRYAGAIN;
+	}
+	strncpy(*buffer, sptr, slen);
+	(*buffer)[slen] = '\0';
+	
+	
+	*valptr = *buffer;
+	
+	*buffer += slen + 1;
+	*buflen -= slen + 1;
+	
+	return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status getgroupmemarray(PGresult *res, 
+                                 struct group *result, 
+                                 char *buffer, size_t buflen, int row, int *errnop)
+{
+	char *sptr, *saveptr;
+	int end = 0;
+	int n;
+	int t;
+
+	enum nss_status status = NSS_STATUS_NOTFOUND;
+	size_t ptrsize;
+
+        // TODO - parse array member and get number of elements
+
+	sptr = PQgetvalue(res, row, GROUP_MEM);
+	end = strlen(sptr) - 1;
+
+	if (end < 2) {
+		end = 0;
+	}
+	char *token[end+1];
+	if ( (0 == strncmp(sptr, "{", 1)) && (0 == strncmp(sptr+end, "}", 1)) ) {
+		sptr[end] = '\0';
+		sptr++;
+	}
+	for (n = 0 ; ; sptr = NULL, n++) {
+		if ( (token[n] = strtok_r(sptr, ",", &saveptr) ) == NULL )
+		break;
+	}
+
+	// Make sure there's enough room for the array of pointers to group member names
+	ptrsize = (n+1) * sizeof(const char *);
+	if(buflen < ptrsize) {
+		status = NSS_STATUS_TRYAGAIN;
+		*errnop = ERANGE;
+		return status;
+	}
+
+	result->gr_mem = (char**)buffer;
+
+	buffer += (ptrsize+3)&(~0x3);
+	buflen -= (ptrsize+3)&(~0x3);
+
+	status = NSS_STATUS_SUCCESS;
+
+	for(t = 0; t < n; t++) {
+		status = copy_attr_grouparray(token[t], &(result->gr_mem[t]), &buffer, &buflen, errnop);
+		if(status != NSS_STATUS_SUCCESS)
+			return status;
+	}
+	result->gr_mem[t] = NULL;
+
+	return status;
+}
+
 
 /*
  * return array of strings containing usernames that are member of group with gid 'gid'
@@ -319,7 +399,8 @@
 
 	result->gr_gid = (gid_t)strtoul(PQgetvalue(res, 0, GROUP_GID), (char**)NULL, 10);
 
-	status = getgroupmem(result->gr_gid, result, buffer, buflen, errnop);
+	status = getgroupmemarray(res, result, buffer, buflen, 0, errnop);
+	if(status != NSS_STATUS_SUCCESS) goto BAIL_OUT;
 
 #ifdef DEBUG
 	if (status == NSS_STATUS_SUCCESS) {
@@ -477,7 +558,7 @@
 	}
 	localerrno = *errnop;
 	PQclear(res);
-	if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) {
+	if (status == NSS_STATUS_TRYAGAIN && localerrno == ERANGE) {
 		res = putback("allgroups");
 		PQclear(res);
 	}
Index: conf/nss-pgsql.conf
===================================================================
--- a/conf/nss-pgsql.conf	(revision 74)
+++ b/conf/nss-pgsql.conf	(working copy)
@@ -11,9 +11,9 @@
 # All users
 allusers        = SELECT username, passwd, gecos, homedir, shell, uid, gid FROM passwd_table
 # Must return group_name, group_passwd, group_gid
-getgrnam        = SELECT groupname, passwd, gid FROM group_table WHERE groupname = $1
+getgrnam        = SELECT groupname, passwd, gid, ARRAY(SELECT username FROM usergroups WHERE usergroups.gid = group_table.gid) AS members FROM group_table WHERE groupname = $1
 # Must return group_name, group_passwd, group_gid
-getgrgid        = SELECT groupname, passwd, gid FROM group_table WHERE gid = $1
+getgrgid        = SELECT groupname, passwd, gid, ARRAY(SELECT username FROM usergroups WHERE usergroups.gid = group_table.gid) AS members FROM group_table WHERE gid = $1
 # Must return gid.  %s MUST appear first for username match in where clause
 groups_dyn      = SELECT ug.gid FROM passwd_table JOIN usergroups USING (uid) where username = $1 and ug.gid <> $2
-allgroups       = SELECT groupname, passwd, gid  FROM group_table
+allgroups       = SELECT groupname, passwd, gid, ARRAY(SELECT username FROM usergroups WHERE usergroups.gid = group_table.gid) AS members FROM group_table