]> andersk Git - moira.git/blame - reg_svr/reg_svr.pc
missed 2 classes in CLASSES; now make clean really does.
[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
78b14dbc 423 {
424 if (status == US_NO_LOGIN_YET)
425 {
426 status = check_kerberos(login);
427 if (status == MR_SUCCESS)
428 status = register_user(rc->uid, login);
429 if (status == MR_IN_USE)
430 {
431 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
432 rc->username);
433 return;
434 }
435 else if (status == MR_DOWN)
436 {
437 reply(rc, DATABASE_CLOSED, "INIT", "c", NULL);
438 return;
439 }
440 else if (status != MR_SUCCESS)
441 {
442 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL,
443 error_message(status));
444 return;
445 }
446 }
447 reply(rc, FORCED_USERNAME, "GETP", "c", NULL, rc->username);
448 }
b50f996d 449}
450
451void SWRD(reg_client *rc, int argc, char **argv)
452{
453 char *words[6];
454 int i;
455
456 if (!rc->id || argc != 6)
457 {
458 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
459 return;
460 }
461
462 getwordlist(rc->id, words);
463 for (i = 0; i < 6; i++)
464 {
465 if (strcasecmp(strtrim(argv[i]), words[i]))
466 break;
467 }
468 if (i != 6)
469 {
470 reply(rc, BAD_SIX_WORDS, "GETW", "d", NULL);
471 return;
472 }
473
474 free(rc->id);
475 rc->id = NULL;
476 if (!rc->username)
477 reply(rc, NO_MESSAGE, "GETL", "c", rc->suggestions);
478 else
479 reply(rc, FORCED_USERNAME, "GETP", "c", NULL, rc->username);
480}
481
482void LOGN(reg_client *rc, int argc, char **argv)
483{
484 int i;
485 char *login;
486 long status;
487
488 if (!rc->uid || rc->id || rc->username || argc != 1)
489 {
490 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
491 return;
492 }
493
494 login = argv[0];
495
496 /* make sure someone's not trying to overrun reply */
497 if (strlen(login) > 100)
498 {
499 com_err(whoami, 0, "Buffer overrun attempted? Closing connection");
500 rc->lastmod = 0;
501 return;
502 }
503
504 if ((strlen(login) < 3) || (strlen(login) > USERS_LOGIN_SIZE - 1) ||
505 (login[0] == '_') || isdigit(login[0]))
506 {
507 reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login,
508 3, USERS_LOGIN_SIZE - 1);
509 return;
510 }
511
512 for (i = 0; i < strlen(login); i++)
513 {
514 if (!islower(login[i]) && !isdigit(login[i]) && (login[i] != '_'))
515 {
516 reply(rc, BAD_USERNAME, "GETL", "c", rc->suggestions, login,
517 3, USERS_LOGIN_SIZE - 1);
518 return;
519 }
520 }
521
522 status = check_kerberos(login);
523 if (status == MR_SUCCESS)
524 status = register_user(rc->uid, login);
525
526 if (status == MR_IN_USE)
527 {
528 if (rc->reserved_username)
529 {
530 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
531 rc->username);
532 return;
533 }
534 reply(rc, USERNAME_UNAVAILABLE, "GETL", "c", rc->suggestions);
535 return;
536 }
537 else if (status == MR_DOWN)
538 {
539 reply(rc, DATABASE_CLOSED, "INIT", "c", NULL);
540 return;
541 }
542 else if (status != MR_SUCCESS)
543 {
544 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, error_message(status));
545 return;
546 }
547
548 rc->username = strdup(login);
549 if (!rc->username)
550 {
551 com_err(whoami, errno, "in LOGN");
552 reply(rc, INTERNAL_ERROR, "INIT", "c", NULL, "Out of memory");
553 return;
554 }
555 reply(rc, USERNAME_OK, "GETP", "c", NULL, login);
556}
557
558int ctypes[256] = {
559 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ^@ - ^O */
560 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ^P - ^_ */
561 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* SPACE - / */
562 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, /* 0 - ? */
563 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* : - O */
564 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, /* P - _ */
565 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* ` - o */
566 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, /* p - ^? */
567 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
568 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
569 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
570 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
571 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
572 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
573 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
574 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
575};
576
577void PSWD(reg_client *rc, int argc, char **argv)
578{
579 long status;
580 char *password = argv[0], *p;
581 EXEC SQL BEGIN DECLARE SECTION;
582 char *login = rc->username;
583 EXEC SQL END DECLARE SECTION;
584
585 if (!rc->username || rc->id || argc != 1)
586 {
587 reply(rc, PROTOCOL_ERROR, "INIT", "c", NULL);
588 return;
589 }
590
591 /* password quality checking */
592 if (strlen(password) < 4)
593 {
594 reply(rc, PASSWORD_SHORT, "GETP", "c", NULL);
595 return;
596 }
597
598 if (strlen(password) < 7)
599 {
600 for (p = password + 1; *p; p++)
601 {
602 if (ctypes[*p] != ctypes[*(p - 1)])
603 break;
604 }
605 if (!*p)
606 {
607 reply(rc, PASSWORD_SIMPLE, "GETP", "c", NULL);
608 return;
609 }
610 }
611
612 if (!strcasecmp(password, "GykoR-66") ||
613 !strcasecmp(password, "slaRooBey") ||
614 !strcasecmp(password, "krang-its") ||
615 !strcasecmp(password, "2HotPeetzas") ||
616 !strcasecmp(password, "ItzAGurl"))
617 {
618 reply(rc, PASSWORD_SAMPLE, "GETP", "c", NULL);
619 return;
620 }
621
622 status = register_kerberos(rc->username, password);
9c0c1480 623 if (status == MR_QUALITY)
624 {
625 reply(rc, PASSWORD_SIMPLE, "GETP", "c", NULL);
626 return;
627 }
628 else if (status == MR_IN_USE)
b50f996d 629 {
630 reply(rc, RESERVED_USERNAME_UNAVAILABLE, "INIT", "c", NULL,
631 rc->username);
632 return;
633 }
634 else if (status)
635 {
636 com_err(whoami, status, "registering username with Kerberos");
637 reply(rc, KADM_ERROR, "INIT", "c", NULL, error_message(status));
638 return;
639 }
640 EXEC SQL UPDATE users SET status = 1 WHERE login = :login;
641 EXEC SQL COMMIT;
642
643 reply(rc, DONE, "INIT", "c", NULL, rc->username);
644}
645
646void QUIT(reg_client *rc, int argc, char **argv)
647{
648}
649
650/* Register a user in Moira */
651int register_user(int uid, char *username)
652{
653 char uidbuf[10], *qargv[3], *motd = NULL;
654 long status;
655
656 status = mr_connect(hostname);
657 if (status)
658 return status;
659
660 status = mr_motd(&motd);
661 if (status || motd)
662 {
663 mr_disconnect();
664 return MR_DOWN;
665 }
666
667 status = krb_get_svc_in_tkt(REG_SVR_PRINCIPAL, REG_SVR_INSTANCE,
668 krb_realmofhost(hostname), MOIRA_SNAME,
669 shorthostname, 1, KEYFILE);
670 if (status)
671 status += ERROR_TABLE_BASE_krb;
672 else
673 status = mr_auth("reg_svr");
674 if (status)
675 {
676 com_err(whoami, status, "authenticating to moira");
677 mr_disconnect();
678 return MR_INTERNAL;
679 }
680
681 sprintf(uidbuf, "%d", uid);
682 qargv[0] = uidbuf;
683 qargv[1] = username;
4787f97b 684 qargv[2] = "IMAP";
b50f996d 685 status = mr_query("register_user", 3, qargv, NULL, NULL);
686 mr_disconnect();
687 return status;
688}
689
690
691/* Find some typical available usernames */
692
693char *uname_patterns[] = {
694 "FL", /* johndoe */
695 "fmllllll", /* jmdoe... (last name truncated) */
696 "flllllll", /* jdoe.... ("") */
697 "llllllll", /* doe..... ("") */
698 "fml", /* jmd */
699 "Fl", /* johnd */
700 "Lf", /* doej */
701 "Lfm", /* doejm */
702 "F", /* john */
703};
704int num_patterns = sizeof(uname_patterns) / sizeof(char *);
705
706char *find_usernames(char *first, char *middle, char *last)
707{
708 EXEC SQL BEGIN DECLARE SECTION;
709 char username[2 * USERS_LOGIN_SIZE];
710 int count;
711 EXEC SQL END DECLARE SECTION;
712 int pat, len;
713 char *pp, *up, *fp, *mp, *lp, *unames = NULL;
714
715 fixname(first);
716 fixname(middle);
717 fixname(last);
718
719 for (pat = 0; pat < num_patterns; pat++)
720 {
721 up = username;
722 fp = first;
723 mp = middle;
724 lp = last;
725 for (pp = uname_patterns[pat]; *pp; pp++)
726 {
727 switch (*pp)
728 {
729 case 'f':
730 if (*fp)
731 *up++ = *fp++;
732 break;
733
734 case 'F':
735 if (up - username + strlen(first) < USERS_LOGIN_SIZE)
736 up += sprintf(up, "%s", first);
737 else
738 goto nextpattern;
739 break;
740
741 case 'm':
742 if (!*middle)
743 goto nextpattern;
744 if (*mp)
745 *up++ = *mp++;
746 break;
747
748 case 'l':
749 if (*lp)
750 *up++ = *lp++;
751 break;
752
753 case 'L':
754 if (up - username + strlen(last) < USERS_LOGIN_SIZE)
755 up += sprintf(up, "%s", last);
756 else
757 goto nextpattern;
758 break;
759 }
760 }
761 *up = '\0';
762
d1d04a6c 763 if (strlen(username) < 3 || strlen(username) >= USERS_LOGIN_SIZE)
b50f996d 764 continue;
765
766 EXEC SQL SELECT COUNT(login) INTO :count FROM users
767 WHERE login = :username;
768 if (sqlca.sqlcode)
8dc13a24 769 {
770 errno = MR_DBMS_ERR;
771 return NULL;
772 }
b50f996d 773 if (count == 0)
774 {
775 EXEC SQL SELECT COUNT(name) INTO :count FROM list
776 WHERE name = :username;
777 if (sqlca.sqlcode)
8dc13a24 778 {
779 errno = MR_DBMS_ERR;
780 return NULL;
781 }
b50f996d 782 }
783 if (count == 0)
784 {
785 EXEC SQL SELECT COUNT(label) INTO :count FROM filesys
786 WHERE label = :username;
787 if (sqlca.sqlcode)
8dc13a24 788 {
789 errno = MR_DBMS_ERR;
790 return NULL;
791 }
b50f996d 792 }
793
794 if (count == 0)
795 {
796 if (unames)
797 {
798 unames = realloc(unames, strlen(unames) + strlen(username) + 3);
799 if (!unames)
800 return NULL;
801 strcat(unames, ", ");
802 strcat(unames, username);
803 }
804 else
805 {
806 unames = strdup(username);
807 if (!unames)
808 return NULL;
809 }
810 }
811
812 nextpattern:
813 ;
814 }
815
8dc13a24 816 /* unames will be NULL if we couldn't suggest a username. Clear
817 errno so the caller can distinguish this from an error case. */
818 errno = 0;
b50f996d 819 return unames;
820}
821
822void fixname(char *name)
823{
824 char *s, *d;
825
826 for (s = d = name; *s; s++)
827 {
828 if (isalnum(*s))
829 *d++ = tolower(*s);
830 }
831 *d = '\0';
832}
833
834void *xmalloc(size_t bytes)
835{
836 void *buf = malloc(bytes);
837
838 if (buf)
839 return buf;
840
841 com_err(whoami, errno, "in xmalloc");
842 exit(1);
843}
844
845void *xrealloc(void *ptr, size_t bytes)
846{
847 void *buf = realloc(ptr, bytes);
848
849 if (buf)
850 return buf;
851
852 com_err(whoami, errno, "in xrealloc");
853 exit(1);
854}
855
856char *xstrdup(char *str)
857{
858 char *buf = strdup(str);
859
860 if (buf)
861 return buf;
862
863 com_err(whoami, errno, "in xstrdup");
864 exit(1);
865}
866
867void mr_com_err(const char *whoami, long code, const char *fmt, va_list pvar)
868{
869 if (whoami)
870 {
871 fputs(whoami, stderr);
872 if (cl)
873 fprintf(stderr, "[#%d]", cl->clientid);
874 fputs(": ", stderr);
875 }
876 if (code) {
877 fputs(error_message(code), stderr);
878 fputs(" ", stderr);
879 }
880 if (fmt)
881 vfprintf(stderr, fmt, pvar);
882 putc('\n', stderr);
883}
884
885void sigshut(int sig)
886{
887 state = RS_EXITING;
888}
This page took 0.179676 seconds and 5 git commands to generate.