]> andersk Git - moira.git/blame - reg_svr/reg_svr.pc
When run with -v, output the words with a "dopage" at the end, suitable
[moira.git] / reg_svr / reg_svr.pc
CommitLineData
b50f996d 1/* $Id$
2 *
3 * Server for user registration with Moira and Kerberos.
4 *
5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
8 */
9
10#include <mit-copyright.h>
11#include <moira.h>
12#include <mr_private.h>
13#include <moira_schema.h>
14#include <moira_site.h>
15#include "reg_svr.h"
16
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <sys/stat.h>
20#include <sys/time.h>
21#include <sys/utsname.h>
22
23#include <netinet/in.h>
24#include <netdb.h>
25
26#include <ctype.h>
27#include <errno.h>
28#include <signal.h>
29#include <stdarg.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34
35#include <com_err.h>
36#include <krb.h>
37
38EXEC SQL INCLUDE sqlca;
39
40RCSID("$Header$");
41
42char *whoami, *hostname, *shorthostname;
43
44char *find_usernames(char *first, char *middle, char *last);
45void fixname(char *name);
46int register_user(int uid, char *username);
47void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar);
48void sigshut(int);
49
50reg_client *cl = NULL;
51enum { RS_RUNNING, RS_SLEEPING, RS_EXITING } state = RS_RUNNING;
52
53int main(int argc, char **argv)
54{
55 int listener, nfds, i, clientid = 0;
56 fd_set readfds, xreadfds;
57 reg_client *clients;
58 int nclients, clientssize;
59 long status;
60 char *db = "moira";
61 struct utsname uts;
62 struct hostent *h;
63 struct sigaction sa;
64 struct stat st;
65
66 whoami = strrchr(argv[0], '/');
67 whoami = whoami ? whoami + 1 : argv[0];
68
69 set_com_err_hook(mr_com_err);
70
71 /* Read keys */
72 if (!read_rsa_key())
73 {
74 com_err(whoami, errno, "reading RSA key");
75 exit(1);
76 }
77 if (!read_hmac_key())
78 {
79 com_err(whoami, errno, "reading HMAC key");
80 exit(1);
81 }
82
83 /* Read error messages */
84 if (!read_errors())
85 {
86 com_err(whoami, errno, "reading error messages");
87 exit(1);
88 }
89
90 /* Connect to database */
91 EXEC SQL CONNECT :db IDENTIFIED BY :db;
92 if (sqlca.sqlcode)
93 {
94 char err_msg[256];
95 int bufsize = 256, msglength = 0;
96
97 sqlglm(err_msg, &bufsize, &msglength);
98 err_msg[msglength] = 0;
99 com_err(whoami, 0, "SQL error connecting to DBMS:\n%s", err_msg);
100 exit(1);
101 }
102
103 /* Get my hostname */
104 uname(&uts);
105 h = gethostbyname(uts.nodename);
106 if (!h)
107 {
108 com_err(whoami, 0, "Couldn't resolve hostname %s", uts.nodename);
109 exit(1);
110 }
111 hostname = lowercase(xstrdup(h->h_name));
112 shorthostname = xstrdup(hostname);
113 if (strchr(shorthostname, '.'))
114 *strchr(shorthostname, '.') = '\0';
115
116 /* Initialize kerberos */
117 status = init_kerberos();
118 if (status)
119 {
120 com_err(whoami, status, "initializing kerberos library");
121 exit(1);
122 }
123
124 /* Set up listening socket. */
125 listener = mr_listen("moira_ureg");
126 if (listener < 0)
127 {
128 com_err(whoami, errno, "couldn't create listening socket");
129 exit(1);
130 }
131 FD_ZERO(&xreadfds);
132 FD_SET(listener, &xreadfds);
133 nfds = listener + 1;
134
135 /* Initialize client array. */
136 nclients = 0;
137 clientssize = 5;
138 clients = malloc(clientssize * sizeof(reg_client));
139 if (!clients)
140 {
141 com_err(whoami, errno, "creating client array");
142 exit(1);
143 }
144
145 /* Set up signal handlers */
146 sa.sa_flags = 0;
147 sigemptyset(&sa.sa_mask);
148 sa.sa_handler = sigshut;
149 sigaction(SIGTERM, &sa, NULL);
150 sigaction(SIGINT, &sa, NULL);
151 sigaction(SIGHUP, &sa, NULL);
152 sa.sa_handler = SIG_IGN;
153 sigaction(SIGPIPE, &sa, NULL);
154
155 com_err(whoami, 0, "started (pid %d)", getpid());
156 com_err(whoami, 0, rcsid);
157
158 /* Main loop */
159 while (state != RS_EXITING)
160 {
161 if (state == RS_RUNNING && stat(MOIRA_MOTD_FILE, &st) == 0)
162 {
9dcee057 163 state = RS_SLEEPING;
b50f996d 164 com_err(whoami, 0, "found motd. reg_svr is sleeping");
165 }
166 else if (state == RS_SLEEPING && stat(MOIRA_MOTD_FILE, &st) == -1)
167 {
9dcee057 168 state = RS_RUNNING;
b50f996d 169 com_err(whoami, 0, "motd gone. reg_svr is running");
170 }
171
172 memcpy(&readfds, &xreadfds, sizeof(readfds));
173 if (select(nfds, &readfds, NULL, NULL, NULL) == -1)
174 {
175 if (errno != EINTR)
176 com_err(whoami, errno, "in select");
177 continue;
178 }
179
180 if (FD_ISSET(listener, &readfds))
181 {
182 int newconn, addrlen = sizeof(struct sockaddr_in);
183 struct sockaddr_in addr;
184
185 newconn = accept(listener, (struct sockaddr *)&addr, &addrlen);
186 if (newconn < 0)
187 com_err(whoami, errno, "accepting new connection");
188 else
189 {
190 nclients++;
191 if (nclients > clientssize)
192 {
193 clientssize = 2 * clientssize;
194 clients = xrealloc(clients, clientssize *
195 sizeof(reg_client));
196 }
197
198 cl = &clients[nclients - 1];
199 memset(cl, 0, sizeof(reg_client));
200 cl->fd = newconn;
201 cl->lastmod = time(NULL);
202 cl->clientid = ++clientid;
203 cl->random = init_rand(cl);
204 FD_SET(newconn, &xreadfds);
205 if (newconn >= nfds)
206 nfds = newconn + 1;
207
208 com_err(whoami, 0,
209 "New connection from %s port %d (now %d client%s)",
210 inet_ntoa(addr.sin_addr), (int)ntohs(addr.sin_port),
211 nclients, nclients != 1 ? "s" : "");
212 }
213 }
214
215 for (i = 0; i < nclients; i++)
216 {
217 cl = &clients[i];
218 if (FD_ISSET(cl->fd, &readfds))
219 {
220 cl->lastmod = time(NULL);
221 if (!cl->buf)
222 {
223 /* We're just starting */
224 cl->buf = malloc(3);
225 if (!cl->buf)
226 {
227 com_err(whoami, errno, "allocating read buffer");
228 reply(cl, INTERNAL_ERROR, "INIT", "c", NULL,
229 "Out of memory");
230 goto reap;
231 }
232 cl->nread = 0;
233 }
234
235 if (cl->nread < 3)
236 {
237 /* We haven't read the length byte yet... */
238 cl->nread += read(cl->fd, cl->buf + cl->nread,
239 3 - cl->nread);
240 if (cl->nread == 3)
241 {
242 cl->nmax = cl->buf[1] * 256 + cl->buf[2] + 3;
243 cl->buf = realloc(cl->buf, cl->nmax + 3);
244 if (!cl->buf)
245 {
246 com_err(whoami, errno, "reallocating read buffer");
247 reply(cl, INTERNAL_ERROR, "INIT", "c", NULL,
248 "Out of memory");
249 goto reap;
250 }
251 }
252 else if (cl->nread == 0)
253 {
254 /* client has closed connection. setting
255 lastmod will cause it to be reaped */
256 cl->lastmod = 0;
257 }
258 }
259 else
260 {
261 /* We know how long the packet is supposed to be */
262 cl->nread += read(cl->fd, cl->buf + cl->nread,
263 cl->nmax - cl->nread);
264 if (cl->nread == cl->nmax)
265 {
266 parse_packet(cl, cl->buf[0], cl->nread - 3, cl->buf + 3,
267 state == RS_SLEEPING);
268 free(cl->buf);
269 cl->buf = NULL;
270 }
271 }
272 }
273
274 reap:
275 if (cl->lastmod < time(NULL) - TIMEOUT)
276 {
277 com_err(whoami, 0, "Closed connection. (now %d client%s)",
278 nclients - 1, nclients != 2 ? "s" : "");
279 shutdown(cl->fd, 2);
280 close(cl->fd);
281 FD_CLR(cl->fd, &xreadfds);
282 free(cl->buf);
283 free(cl->id);
284 free(cl->username);
285 free(cl->suggestions);
286 free(cl->random);
287 clients[i] = clients[--nclients];
288 i--;
289 }
290 }
291 cl = NULL;
292 }
293 com_err(whoami, 0, "Exiting.");
294}
295
296void RIFO(reg_client *rc, int argc, char **argv)
297{
298 EXEC SQL BEGIN DECLARE SECTION;
299 char *ufirst, *umiddle, *ulast, *id;
300 char login[USERS_LOGIN_SIZE], first[USERS_FIRST_SIZE];
301 char middle[USERS_MIDDLE_SIZE], last[USERS_LAST_SIZE];
302 char fullname[USERS_FIRST_SIZE + USERS_MIDDLE_SIZE + USERS_LAST_SIZE];
303 char class[USERS_TYPE_SIZE];
304 int uid, status, secure, sqlstatus;
305 EXEC SQL END DECLARE SECTION;
306
307 if (rc->uid || argc != 4)
308 {
309 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
310 return;
311 }
312
313 ufirst = argv[0];
314 umiddle = argv[1];
315 ulast = argv[2];
316 id = argv[3];
317
318 /* "ORDER BY status" so that if there's both a matching state 0 entry
319 and a matching state 3 entry, we'll get the former. */
320 EXEC SQL DECLARE csr_id CURSOR FOR
321 SELECT login, unix_uid, status, secure, first, middle, last, type
322 FROM users WHERE clearid = :id ORDER BY status;
323 EXEC SQL OPEN csr_id;
324 while (1)
325 {
326 EXEC SQL FETCH csr_id INTO :login, :uid, :status,
327 :secure, :first, :middle, :last, :class;
328 if (sqlca.sqlcode)
329 break;
330 strtrim(login);
331 strtrim(first);
332 strtrim(middle);
333 strtrim(last);
334 strtrim(class);
335
336 /* Check names, allowing for the possibility that Moira and the
337 user might have them split up differently. eg, Mary/Ann/Singleton
338 vs. Mary Ann/Singleton. */
339 if (strcasecmp(last, ulast) && strncasecmp(last, ulast, strlen(last)) &&
340 strncasecmp(last, ulast, strlen(ulast)))
341 continue;
342 if (strlen(last) > 3 && strlen(ulast) < 3)
343 continue;
344 if (strcasecmp(first, ufirst) &&
345 strncasecmp(first, ufirst, strlen(first)) &&
346 strncasecmp(first, ufirst, strlen(ufirst)))
347 continue;
348 if (strlen(first) > 3 && strlen(ufirst) < 3)
349 continue;
350 /* Ignore the middle name since Moira doesn't have those reliably */
351 break;
352 }
353 sqlstatus = sqlca.sqlcode;
354 EXEC SQL CLOSE csr_id;
355
356 if (sqlstatus)
357 {
358 reply(rc, NOT_FOUND_IN_DATABASE, "GETN", "d", NULL);
359 return;
360 }
361
362 switch (status)
363 {
364 case US_REGISTERED:
365 case US_ENROLLED:
366 case US_ENROLL_NOT_ALLOWED:
367 reply(rc, ALREADY_REGISTERED, "INIT", "c", NULL, login);
368 return;
369
370 case US_DELETED:
371 reply(rc, ACCOUNT_DELETED, "INIT", "c", NULL, login);
372 return;
373
374 case US_NOT_ALLOWED:
375 reply(rc, NOT_ELIGIBLE, "INIT", "c", NULL);
376 return;
377
378 default:
379 break;
380 }
381
382 rc->uid = uid;
383 sprintf(fullname, "%s %s%s%s", first, middle, *middle ? " " : "", last);
384 if (!strcmp(class, "MITS"))
385 strcpy(class, "STAFF");
386 if (secure == 1)
387 {
388 rc->id = strdup(id);
389 if (!rc->id)
390 {
391 com_err(whoami, errno, "in RIFO");
392 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, "Out of memory");
393 return;
394 }
395 }
396 if (*login != '#')
397 {
398 rc->reserved_username = 1;
399 rc->username = strdup(login);
400 if (!rc->username)
401 {
402 com_err(whoami, errno, "in RIFO");
403 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, "Out of memory");
404 return;
405 }
406 }
407 else
408 {
409 rc->suggestions = find_usernames(first, middle, last);
8dc13a24 410 if (!rc->suggestions && errno)
b50f996d 411 {
412 com_err(whoami, errno, "in RIFO");
8dc13a24 413 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, error_message(errno));
b50f996d 414 return;
415 }
416 }
417
418 if (rc->id)
419 reply(rc, FOUND, "GETW", "c", NULL, fullname, class);
420 else if (!rc->username)
421 reply(rc, FOUND, "GETL", "c", rc->suggestions, fullname, class);
422 else
84005ecc 423 reply(rc, FORCED_USERNAME, "GETP", "c", NULL, rc->username);
b50f996d 424}
425
426void SWRD(reg_client *rc, int argc, char **argv)
427{
428 char *words[6];
429 int i;
430
431 if (!rc->id || argc != 6)
432 {
433 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
434 return;
435 }
436
437 getwordlist(rc->id, words);
438 for (i = 0; i < 6; i++)
439 {
440 if (strcasecmp(strtrim(argv[i]), words[i]))
441 break;
442 }
443 if (i != 6)
444 {
445 reply(rc, BAD_SIX_WORDS, "GETW", "d", NULL);
446 return;
447 }
448
449 free(rc->id);
450 rc->id = NULL;
451 if (!rc->username)
452 reply(rc, NO_MESSAGE, "GETL", "c", rc->suggestions);
453 else
454 reply(rc, FORCED_USERNAME, "GETP", "c", NULL, rc->username);
455}
456
457void LOGN(reg_client *rc, int argc, char **argv)
458{
459 int i;
460 char *login;
461 long status;
462
463 if (!rc->uid || rc->id || rc->username || argc != 1)
464 {
465 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
466 return;
467 }
468
469 login = argv[0];
470
471 /* make sure someone's not trying to overrun reply */
472 if (strlen(login) > 100)
473 {
474 com_err(whoami, 0, "Buffer overrun attempted? Closing connection");
475 rc->lastmod = 0;
476 return;
477 }
478
479 if ((strlen(login) < 3) || (strlen(login) > USERS_LOGIN_SIZE - 1) ||
480 (login[0] == '_') || isdigit(login[0]))
481 {
482 reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login,
483 3, USERS_LOGIN_SIZE - 1);
484 return;
485 }
486
487 for (i = 0; i < strlen(login); i++)
488 {
489 if (!islower(login[i]) && !isdigit(login[i]) && (login[i] != '_'))
490 {
491 reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login,
492 3, USERS_LOGIN_SIZE - 1);
493 return;
494 }
495 }
496
497 status = check_kerberos(login);
498 if (status == MR_SUCCESS)
499 status = register_user(rc->uid, login);
500
501 if (status == MR_IN_USE)
502 {
503 if (rc->reserved_username)
504 {
505 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
506 rc->username);
507 return;
508 }
509 reply(rc, USERNAME_UNAVAILABLE, "GETL", "c", rc->suggestions);
510 return;
511 }
512 else if (status == MR_DOWN)
513 {
514 reply(rc, DATABASE_CLOSED, "INIT", "c", NULL);
515 return;
516 }
517 else if (status != MR_SUCCESS)
518 {
519 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, error_message(status));
520 return;
521 }
522
523 rc->username = strdup(login);
524 if (!rc->username)
525 {
526 com_err(whoami, errno, "in LOGN");
527 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, "Out of memory");
528 return;
529 }
530 reply(rc, USERNAME_OK, "GETP", "c", NULL, login);
531}
532
533int ctypes[256] = {
534 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ^@ - ^O */
535 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ^P - ^_ */
536 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* SPACE - / */
537 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, /* 0 - ? */
538 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* : - O */
539 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, /* P - _ */
540 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* ` - o */
541 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, /* p - ^? */
542 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
543 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
544 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
545 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
546 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
547 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
548 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
549 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
550};
551
552void PSWD(reg_client *rc, int argc, char **argv)
553{
554 long status;
555 char *password = argv[0], *p;
556 EXEC SQL BEGIN DECLARE SECTION;
557 char *login = rc->username;
558 EXEC SQL END DECLARE SECTION;
559
560 if (!rc->username || rc->id || argc != 1)
561 {
562 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
563 return;
564 }
565
566 /* password quality checking */
567 if (strlen(password) < 4)
568 {
569 reply(rc, PASSWORD_SHORT, "GETP", "c", NULL);
570 return;
571 }
572
573 if (strlen(password) < 7)
574 {
575 for (p = password + 1; *p; p++)
576 {
577 if (ctypes[*p] != ctypes[*(p - 1)])
578 break;
579 }
580 if (!*p)
581 {
582 reply(rc, PASSWORD_SIMPLE, "GETP", "c", NULL);
583 return;
584 }
585 }
586
587 if (!strcasecmp(password, "GykoR-66") ||
588 !strcasecmp(password, "slaRooBey") ||
589 !strcasecmp(password, "krang-its") ||
590 !strcasecmp(password, "2HotPeetzas") ||
591 !strcasecmp(password, "ItzAGurl"))
592 {
593 reply(rc, PASSWORD_SAMPLE, "GETP", "c", NULL);
594 return;
595 }
596
597 status = register_kerberos(rc->username, password);
9c0c1480 598 if (status == MR_QUALITY)
599 {
600 reply(rc, PASSWORD_SIMPLE, "GETP", "c", NULL);
601 return;
602 }
603 else if (status == MR_IN_USE)
b50f996d 604 {
605 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
606 rc->username);
607 return;
608 }
609 else if (status)
610 {
611 com_err(whoami, status, "registering username with Kerberos");
612 reply(rc, KADM_ERROR, "INIT", "c", NULL, error_message(status));
613 return;
614 }
615 EXEC SQL UPDATE users SET status = 1 WHERE login = :login;
616 EXEC SQL COMMIT;
617
618 reply(rc, DONE, "INIT", "c", NULL, rc->username);
619}
620
621void QUIT(reg_client *rc, int argc, char **argv)
622{
623}
624
625/* Register a user in Moira */
626int register_user(int uid, char *username)
627{
628 char uidbuf[10], *qargv[3], *motd = NULL;
629 long status;
630
631 status = mr_connect(hostname);
632 if (status)
633 return status;
634
635 status = mr_motd(&motd);
636 if (status || motd)
637 {
638 mr_disconnect();
639 return MR_DOWN;
640 }
641
642 status = krb_get_svc_in_tkt(REG_SVR_PRINCIPAL, REG_SVR_INSTANCE,
643 krb_realmofhost(hostname), MOIRA_SNAME,
644 shorthostname, 1, KEYFILE);
645 if (status)
646 status += ERROR_TABLE_BASE_krb;
647 else
648 status = mr_auth("reg_svr");
649 if (status)
650 {
651 com_err(whoami, status, "authenticating to moira");
652 mr_disconnect();
653 return MR_INTERNAL;
654 }
655
656 sprintf(uidbuf, "%d", uid);
657 qargv[0] = uidbuf;
658 qargv[1] = username;
4787f97b 659 qargv[2] = "IMAP";
b50f996d 660 status = mr_query("register_user", 3, qargv, NULL, NULL);
661 mr_disconnect();
662 return status;
663}
664
665
666/* Find some typical available usernames */
667
668char *uname_patterns[] = {
669 "FL", /* johndoe */
670 "fmllllll", /* jmdoe... (last name truncated) */
671 "flllllll", /* jdoe.... ("") */
672 "llllllll", /* doe..... ("") */
673 "fml", /* jmd */
674 "Fl", /* johnd */
675 "Lf", /* doej */
676 "Lfm", /* doejm */
677 "F", /* john */
678};
679int num_patterns = sizeof(uname_patterns) / sizeof(char *);
680
681char *find_usernames(char *first, char *middle, char *last)
682{
683 EXEC SQL BEGIN DECLARE SECTION;
684 char username[2 * USERS_LOGIN_SIZE];
685 int count;
686 EXEC SQL END DECLARE SECTION;
687 int pat, len;
688 char *pp, *up, *fp, *mp, *lp, *unames = NULL;
689
690 fixname(first);
691 fixname(middle);
692 fixname(last);
693
694 for (pat = 0; pat < num_patterns; pat++)
695 {
696 up = username;
697 fp = first;
698 mp = middle;
699 lp = last;
700 for (pp = uname_patterns[pat]; *pp; pp++)
701 {
702 switch (*pp)
703 {
704 case 'f':
705 if (*fp)
706 *up++ = *fp++;
707 break;
708
709 case 'F':
710 if (up - username + strlen(first) < USERS_LOGIN_SIZE)
711 up += sprintf(up, "%s", first);
712 else
713 goto nextpattern;
714 break;
715
716 case 'm':
717 if (!*middle)
718 goto nextpattern;
719 if (*mp)
720 *up++ = *mp++;
721 break;
722
723 case 'l':
724 if (*lp)
725 *up++ = *lp++;
726 break;
727
728 case 'L':
729 if (up - username + strlen(last) < USERS_LOGIN_SIZE)
730 up += sprintf(up, "%s", last);
731 else
732 goto nextpattern;
733 break;
734 }
735 }
736 *up = '\0';
737
d1d04a6c 738 if (strlen(username) < 3 || strlen(username) >= USERS_LOGIN_SIZE)
b50f996d 739 continue;
740
741 EXEC SQL SELECT COUNT(login) INTO :count FROM users
742 WHERE login = :username;
743 if (sqlca.sqlcode)
8dc13a24 744 {
745 errno = MR_DBMS_ERR;
746 return NULL;
747 }
b50f996d 748 if (count == 0)
749 {
750 EXEC SQL SELECT COUNT(name) INTO :count FROM list
751 WHERE name = :username;
752 if (sqlca.sqlcode)
8dc13a24 753 {
754 errno = MR_DBMS_ERR;
755 return NULL;
756 }
b50f996d 757 }
758 if (count == 0)
759 {
760 EXEC SQL SELECT COUNT(label) INTO :count FROM filesys
761 WHERE label = :username;
762 if (sqlca.sqlcode)
8dc13a24 763 {
764 errno = MR_DBMS_ERR;
765 return NULL;
766 }
b50f996d 767 }
768
769 if (count == 0)
770 {
771 if (unames)
772 {
773 unames = realloc(unames, strlen(unames) + strlen(username) + 3);
774 if (!unames)
775 return NULL;
776 strcat(unames, ", ");
777 strcat(unames, username);
778 }
779 else
780 {
781 unames = strdup(username);
782 if (!unames)
783 return NULL;
784 }
785 }
786
787 nextpattern:
788 ;
789 }
790
8dc13a24 791 /* unames will be NULL if we couldn't suggest a username. Clear
792 errno so the caller can distinguish this from an error case. */
793 errno = 0;
b50f996d 794 return unames;
795}
796
797void fixname(char *name)
798{
799 char *s, *d;
800
801 for (s = d = name; *s; s++)
802 {
803 if (isalnum(*s))
804 *d++ = tolower(*s);
805 }
806 *d = '\0';
807}
808
809void *xmalloc(size_t bytes)
810{
811 void *buf = malloc(bytes);
812
813 if (buf)
814 return buf;
815
816 com_err(whoami, errno, "in xmalloc");
817 exit(1);
818}
819
820void *xrealloc(void *ptr, size_t bytes)
821{
822 void *buf = realloc(ptr, bytes);
823
824 if (buf)
825 return buf;
826
827 com_err(whoami, errno, "in xrealloc");
828 exit(1);
829}
830
831char *xstrdup(char *str)
832{
833 char *buf = strdup(str);
834
835 if (buf)
836 return buf;
837
838 com_err(whoami, errno, "in xstrdup");
839 exit(1);
840}
841
842void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar)
843{
844 if (whoami)
845 {
846 fputs(whoami, stderr);
847 if (cl)
848 fprintf(stderr, "[#%d]", cl->clientid);
849 fputs(": ", stderr);
850 }
851 if (code) {
852 fputs(error_message(code), stderr);
853 fputs(" ", stderr);
854 }
855 if (fmt)
856 vfprintf(stderr, fmt, pvar);
857 putc('\n', stderr);
858}
859
860void sigshut(int sig)
861{
862 state = RS_EXITING;
863}
This page took 0.170713 seconds and 5 git commands to generate.