+void auth_unix_gid(FILE *f)
+{
+ /* Request are
+ * uid
+ * reply is
+ * uid expiry count list of group ids
+ */
+ int uid;
+ struct passwd *pw;
+ gid_t glist[100], *groups = glist;
+ int ngroups = 100;
+ int rv, i;
+ char *cp;
+
+ if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+ return;
+
+ cp = lbuf;
+ if (qword_get_int(&cp, &uid) != 0)
+ return;
+
+ pw = getpwuid(uid);
+ if (!pw)
+ rv = -1;
+ else {
+ rv = getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
+ if (rv == -1 && ngroups >= 100) {
+ groups = malloc(sizeof(gid_t)*ngroups);
+ if (!groups)
+ rv = -1;
+ else
+ rv = getgrouplist(pw->pw_name, pw->pw_gid,
+ groups, &ngroups);
+ }
+ }
+ qword_printint(f, uid);
+ qword_printint(f, time(0)+30*60);
+ if (rv >= 0) {
+ qword_printint(f, ngroups);
+ for (i=0; i<ngroups; i++)
+ qword_printint(f, groups[i]);
+ }
+ qword_eol(f);
+ if (groups != glist)
+ free(groups);
+}
+
+#if USE_BLKID
+int get_uuid(char *path, char *uuid, int uuidlen, char *u)
+{
+ /* extract hex digits from uuidstr and compose a uuid
+ * of the given length (max 16), xoring bytes to make
+ * a smaller uuid. Then compare with uuid
+ */
+ int i = 0;
+ const char *val;
+
+ if (path) {
+ static blkid_cache cache = NULL;
+ struct stat stb;
+ char *devname;
+ blkid_tag_iterate iter;
+ blkid_dev dev;
+ const char *type;
+ if (cache == NULL)
+ blkid_get_cache(&cache, NULL);
+
+ blkid_probe_all_new(cache);
+
+ if (stat(path, &stb) != 0)
+ return 0;
+ devname = blkid_devno_to_devname(stb.st_dev);
+ if (!devname)
+ return 0;
+ dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
+ free(devname);
+ if (!dev)
+ return 0;
+ iter = blkid_tag_iterate_begin(dev);
+ if (!iter)
+ return 0;
+ while (blkid_tag_next(iter, &type, &val) == 0)
+ if (strcmp(type, "UUID") == 0)
+ break;
+ blkid_tag_iterate_end(iter);
+ if (!type)
+ return 0;
+ } else {
+ val = uuid;
+ }
+
+ memset(u, 0, uuidlen);
+ for ( ; *val ; val++) {
+ char c = *val;
+ if (!isxdigit(c))
+ continue;
+ if (isalpha(c)) {
+ if (isupper(c))
+ c = c - 'A' + 10;
+ else
+ c = c - 'a' + 10;
+ } else
+ c = c - '0' + 0;
+ if ((i&1) == 0)
+ c <<= 4;
+ u[i/2] ^= c;
+ i++;
+ if (i == uuidlen*2)
+ i = 0;
+ }
+ return 1;
+}
+#endif
+
+/* Iterate through /etc/mtab, finding mountpoints
+ * at or below a given path
+ */
+static char *next_mnt(void **v, char *p)
+{
+ FILE *f;
+ struct mntent *me;
+ int l = strlen(p);
+ if (*v == NULL) {
+ f = setmntent("/etc/mtab", "r");
+ *v = f;
+ } else
+ f = *v;
+ while ((me = getmntent(f)) != NULL &&
+ (strncmp(me->mnt_dir, p, l) != 0 ||
+ me->mnt_dir[l] != '/'))
+ ;
+ if (me == NULL) {
+ endmntent(f);
+ *v = NULL;
+ return NULL;
+ }
+ return me->mnt_dir;
+}
+