+
+int retr_callback(int argc, char **argv, void *p_cl)
+{
+ client *cl = p_cl;
+
+ mr_trim_args(argc, argv);
+ client_return_tuple(cl, argc, argv);
+}
+
+void do_access(client *cl)
+{
+ int status;
+
+ if (cl->req.mr_argc < 1)
+ {
+ client_reply(cl, MR_ARGS);
+ com_err(whoami, MR_ARGS, "got nameless access");
+ return;
+ }
+
+ status = mr_check_access(cl, cl->req.mr_argv[0], cl->req.mr_argc - 1,
+ cl->req.mr_argv + 1);
+ client_reply(cl, status);
+
+ com_err(whoami, 0, "Access check complete.");
+}
+
+void do_version(client *cl)
+{
+ if (cl->req.mr_argc != 1)
+ {
+ client_reply(cl, MR_ARGS);
+ com_err(whoami, MR_ARGS, "incorrect number of arguments");
+ return;
+ }
+
+ cl->version = atoi(cl->req.mr_argv[0]);
+ if (cl->version == -1)
+ cl->version = max_version;
+
+ client_reply(cl, cl->version == max_version ? MR_SUCCESS :
+ cl->version < max_version ? MR_VERSION_LOW : MR_VERSION_HIGH);
+}
+
+void get_motd(client *cl)
+{
+ int motd;
+ char *buffer;
+ struct stat statb;
+
+ if (stat(MOIRA_MOTD_FILE, &statb) == -1)
+ {
+ client_reply(cl, MR_SUCCESS);
+ return;
+ }
+
+ buffer = malloc(statb.st_size + 1);
+ if (!buffer)
+ {
+ client_reply(cl, MR_NO_MEM);
+ return;
+ }
+
+ motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
+ if (motd)
+ {
+ read(motd, buffer, statb.st_size);
+ close(motd);
+ buffer[statb.st_size] = '\0';
+ client_return_tuple(cl, 1, &buffer);
+ client_reply(cl, MR_SUCCESS);
+ }
+ else
+ client_reply(cl, errno);
+
+ free(buffer);
+}
+
+int list_users(client *cl)
+{
+ char *argv[5];
+ char buf[30];
+ char buf1[30];
+ int i;
+ char *cp;
+
+ for (i = 0; i < nclients; i++)
+ {
+ client *c = clients[i];
+ argv[0] = c->clname;
+ argv[1] = inet_ntoa(c->haddr.sin_addr);
+ argv[2] = buf;
+ sprintf(buf, "port %d", ntohs(c->haddr.sin_port));
+ argv[3] = ctime(&c->last_time_used);
+ cp = strchr(argv[3], '\n');
+ if (cp)
+ *cp = '\0';
+ argv[4] = buf1;
+ sprintf(buf1, "[#%d]", c->id);
+ client_return_tuple(cl, 5, argv);
+ }
+ return MR_SUCCESS;
+}
+