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