+ ret = read(fd, buf, len);
+ close(fd);
+ if (ret <= 0)
+ return -1;
+ }
+ return 0;
+}
+
+/* afp-specific functions */
+int uam_afpserver_option(void *private, const int what, void *option,
+ size_t *len)
+{
+ AFPObj *obj = private;
+ const char **buf = (const char **) option; /* most of the options are this */
+ struct session_info **sinfo = (struct session_info **) option;
+
+ if (!obj || !option)
+ return -1;
+
+ switch (what) {
+ case UAM_OPTION_USERNAME:
+ *buf = &(obj->username[0]);
+ if (len)
+ *len = sizeof(obj->username) - 1;
+ break;
+
+ case UAM_OPTION_GUEST:
+ *buf = obj->options.guest;
+ if (len)
+ *len = strlen(obj->options.guest);
+ break;
+
+ case UAM_OPTION_PASSWDOPT:
+ if (!len)
+ return -1;
+
+ switch (*len) {
+ case UAM_PASSWD_FILENAME:
+ *buf = obj->options.passwdfile;
+ *len = strlen(obj->options.passwdfile);
+ break;
+
+ case UAM_PASSWD_MINLENGTH:
+ *((int *) option) = obj->options.passwdminlen;
+ *len = sizeof(obj->options.passwdminlen);
+ break;
+
+ case UAM_PASSWD_MAXFAIL:
+ *((int *) option) = obj->options.loginmaxfail;
+ *len = sizeof(obj->options.loginmaxfail);
+ break;
+
+ case UAM_PASSWD_EXPIRETIME: /* not implemented */
+ default:
+ return -1;
+ break;
+ }
+ break;
+
+ case UAM_OPTION_SIGNATURE:
+ *buf = (void *) (((AFPConfig *)obj->config)->signature);
+ if (len)
+ *len = 16;
+ break;
+
+ case UAM_OPTION_RANDNUM: /* returns a random number in 4-byte units. */
+ if (!len)
+ return -1;
+
+ return uam_random_string(obj, option, *len);
+ break;
+
+ case UAM_OPTION_HOSTNAME:
+ *buf = obj->options.hostname;
+ if (len)
+ *len = strlen(obj->options.hostname);
+ break;
+
+ case UAM_OPTION_PROTOCOL:
+ *((int *) option) = obj->proto;
+ break;
+
+ case UAM_OPTION_CLIENTNAME:
+ {
+ struct DSI *dsi = obj->handle;
+ const struct sockaddr *sa;
+ static char hbuf[NI_MAXHOST];
+
+ sa = (struct sockaddr *)&dsi->client;
+ if (getnameinfo(sa, sizeof(dsi->client), hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
+ *buf = hbuf;
+ else
+ *buf = getip_string((struct sockaddr *)&dsi->client);
+
+ break;
+ }
+ case UAM_OPTION_COOKIE:
+ /* it's up to the uam to actually store something useful here.
+ * this just passes back a handle to the cookie. the uam side
+ * needs to do something like **buf = (void *) cookie to store
+ * the cookie. */
+ *buf = (void *) &obj->uam_cookie;
+ break;
+ case UAM_OPTION_KRB5SERVICE:
+ *buf = obj->options.k5service;
+ if (len)
+ *len = (*buf)?strlen(*buf):0;
+ break;
+ case UAM_OPTION_KRB5REALM:
+ *buf = obj->options.k5realm;
+ if (len)
+ *len = (*buf)?strlen(*buf):0;
+ break;
+ case UAM_OPTION_FQDN:
+ *buf = obj->options.fqdn;
+ if (len)
+ *len = (*buf)?strlen(*buf):0;
+ break;
+ case UAM_OPTION_MACCHARSET:
+ *((int *) option) = obj->options.maccharset;
+ *len = sizeof(obj->options.maccharset);
+ break;
+ case UAM_OPTION_UNIXCHARSET:
+ *((int *) option) = obj->options.unixcharset;
+ *len = sizeof(obj->options.unixcharset);
+ break;
+ case UAM_OPTION_SESSIONINFO:
+ *sinfo = &(obj->sinfo);
+ break;
+ default:
+ return -1;
+ break;