+/*
+ * Template string may contain zero or one '~' and zero or one '?'.
+ * '~' at the beginning of the template string is substituted with
+ * the home directory of the userid. In any other position it is
+ * substituted with the userid itself. '?' is substituted with the
+ * tokenid. There is no way to make the resulting path contain '~'
+ * or '?'. If there is more than one '~' or '?', or if the '~' is
+ * at the beginning but userid does not resolve via getpwnam, or
+ * the character to substitute is present but the argument is NULL,
+ * NULL is returned. Otherwise, malloc()'ed area containg the path
+ * string.
+ */
+
+static const char *template = "~/.pam_cr/auth";
+
+void authfile_template(const char *str)
+{
+ template = str;
+}
+
+static int path_size(const char *tokenid, const char *userid)
+{
+ const char *usub;
+ const char *p, *q;
+ struct passwd *pw;
+
+ if ((p = strchr(template, '~')) != strrchr(template, '~')) return 0;
+ if ((q = strchr(template, '?')) != strrchr(template, '?')) return 0;
+ if (p && !userid) return 0;
+ if (q && !tokenid) return 0;
+ if (p == template) {
+ pw = getpwnam(userid);
+ if (!pw) return 0;
+ usub = pw->pw_dir;
+ } else {
+ usub = userid;
+ }
+ return strlen(template)+(p?strlen(usub):0)+(q?strlen(tokenid):0)+1;
+}
+
+static void
+make_path(char * const path, const char *tokenid, const char *userid)
+{
+ const char *usub;
+ const char *p;
+ char *q;
+ struct passwd *pw;
+
+ path[0] = '\0';
+ if (template[0] == '~') {
+ pw = getpwnam(userid);
+ if (!pw) return;
+ usub = pw->pw_dir;
+ } else {
+ usub = userid;
+ }
+ q = path;
+ for (p = template; *p; p++) switch (*p) {
+ case '~':
+ strcpy(q, usub);
+ while (*q) q++;
+ break;
+ case '?':
+ strcpy(q, tokenid);
+ while (*q) q++;
+ break;
+ default:
+ *q++ = *p;
+ break;
+ }
+ *q = '\0';
+}