Merge commit 'b1e7e97d3b60469b243b3b2e22c7d8cbd11c7c90'
[unleashed.git] / usr / src / cmd / listen / lsdbf.c
blob14d1f3b6be548c5d9df5134569c17a48b5b2feac
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
33 * data base routines for the network listener process
36 /* system include files */
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <sys/param.h>
43 #include <sys/types.h>
44 #include <sys/tiuser.h>
45 #include <sys/stropts.h>
47 /* listener include files */
49 #include "lsparam.h" /* listener parameters */
50 #include "listen.h" /* listener includes */
51 #include "lsfiles.h" /* listener files info */
52 #include "lserror.h" /* listener error codes */
53 #include "lsdbf.h" /* data base file stuff */
54 /* #include "nsaddr.h" nls includes */
56 #define SUPPRESS 1 /* suppress messages during scan*/
57 #define NOSUPPRESS 0 /* don't suppress messages */
59 /* static data */
61 static char *dbfopenmsg = "Trouble opening data base file";
62 static char *dbfrderror = "Error reading data base file: line %d";
63 static char *dbfbadlmsg = "Data base file: Error on line %d";
64 static char *dbfdupcmsg = "Data base file: Duplicate service code: <%s>";
65 static char *dbfunknown = "Unknown error reading data base file: line %d";
66 static char *dbfsvccmsg = "Data base file: Illegal service code: <%s>";
67 static char *dbfcorrupt = "Data base file has been corrupted";
69 static int Dbflineno; /* current line number in dbf */
70 static unsigned Dbfentries; /* number of non-comment lines */
71 extern char *Server_cmd_lines; /* contains svc_code, cmd_line, mod_list */
72 extern char *New_cmd_lines; /* svc_code, cmd_line, mod_list (on reread)*/
74 /* public variables */
78 * read_dbf:
80 * read the data base file into internal structures
82 * all data base routines under read_dbf log there own errors and return -1
83 * in case of an error.
85 * if 're_read' is non-zero, this stuff is being called to read a new
86 * data base file after the listener's initialization.
89 int
90 read_dbf(re_read)
91 int re_read; /* zero means first time */
93 register unsigned size;
94 int exit_flag = EXIT | NOCORE;
95 register dbf_t *dbf_p;
96 register char *cmd_p;
97 unsigned scan_dbf();
98 extern dbf_t *Dbfhead; /* Dbfentries (when allocated) */
99 extern dbf_t *Newdbf; /* Dbfentries (on re-read) */
100 extern char *calloc();
102 DEBUG((9,"in read_dbf"));
104 if (check_version())
105 error(E_BADVER, EXIT | NOCORE);
107 if (re_read) { /* not first time */
108 exit_flag = CONTINUE;
112 * note: data base routines log their own error messages
115 Dbfentries = 0;
116 DEBUG((9,"read_dbf: open file here: %s", DBFNAME));
117 if ( (size = scan_dbf(DBFNAME)) == (unsigned)(-1) )
118 error( E_SCAN_DBF, exit_flag | NO_MSG );
120 DEBUG((5,"read_dbf: scan complete: non-commented lines: %u, size: %u",
121 Dbfentries, size));
123 if (!size) {
124 logmessage("No database? 0 entries?");
125 return(0);
129 * allocate enough space for Dbfentries of 'size' bytes (total)
130 * The +1 is to insure a NULL last entry!
133 if (!(dbf_p = (dbf_t *)calloc(Dbfentries+1,sizeof(dbf_t)))
134 || !(cmd_p = calloc(size, 1))) {
135 DEBUG((1,"cannot calloc %u + %u bytes", size,
136 (Dbfentries+1)*(unsigned)sizeof(dbf_t)));
137 error( E_DBF_ALLOC, exit_flag); /* if init, exit */
139 /* if still here, this is a re-read */
141 if (dbf_p)
142 free(dbf_p);
143 if (cmd_p)
144 free(cmd_p);
145 return(-1);
148 if (get_dbf(dbf_p, cmd_p)) {
149 DEBUG((9, "get_dbf FAILED"));
150 error(E_DBF_IO, exit_flag | NO_MSG);
152 /* if still here, this is a re_read */
153 free(dbf_p);
154 free(cmd_p);
155 return(-1);
158 if (re_read) {
159 Newdbf = dbf_p;
160 New_cmd_lines = cmd_p;
161 #ifdef DEBUGMODE
162 DEBUG((7,"read_dbf: NEW data base dump..."));
163 if (Newdbf)
164 for (dbf_p = Newdbf; dbf_p->dbf_svc_code; ++dbf_p)
165 DEBUG((7, "svc code <%s>; id: %s; private address: %s; modules: %s; cmd line: %s; sflags: %x, prognum: %d version: %d",
166 dbf_p->dbf_svc_code, dbf_p->dbf_id, dbf_p->dbf_prv_adr, dbf_p->dbf_modules, dbf_p->dbf_cmd_line, dbf_p->dbf_sflags, dbf_p->dbf_prognum, dbf_p->dbf_version));
167 #endif /* DEBUGMODE */
169 else {
170 Dbfhead = dbf_p;
171 Server_cmd_lines = cmd_p;
172 #ifdef DEBUGMODE
173 DEBUG((7,"read_dbf: data base dump..."));
174 if (Dbfhead)
175 for (dbf_p = Dbfhead; dbf_p->dbf_svc_code; ++dbf_p)
176 DEBUG((7, "svc code <%s>; id: %s; r1: %s; r2: %s; r3: %s; private address: %s; modules: %s; cmd line: %s; sflags: %x, prognum: %d version: %d",
177 dbf_p->dbf_svc_code, dbf_p->dbf_id, dbf_p->dbf_res1, dbf_p->dbf_res2, dbf_p->dbf_res3, dbf_p->dbf_prv_adr, dbf_p->dbf_modules, dbf_p->dbf_cmd_line, dbf_p->dbf_sflags, dbf_p->dbf_prognum, dbf_p->dbf_version));
178 #endif /* DEBUGMODE */
181 return(0);
186 * get_dbf: read the file and fill the structures
187 * checking for duplicate entries as we go
191 get_dbf(dbf_p, cmd_p)
192 register dbf_t *dbf_p;
193 register char *cmd_p;
195 dbf_t *dbfhead = dbf_p;
196 register int n, i;
197 char buf[DBFLINESZ];
198 register char *p = buf;
199 char scratch[128];
200 FILE *dbfilep;
201 char *cmd_line_p;
202 int flags;
203 char *svc_code_p;
204 char *id_p;
205 char *res1_p;
206 char *res2_p;
207 char *res3_p;
208 char *private_p;
209 int sflags;
210 int prognum;
211 int vernum;
212 char *module_p;
213 register dbf_t *tdbf_p;
214 extern int atoi();
215 extern int Dbf_entries;
216 extern int NLPS_proc;
217 extern int errno;
219 Dbflineno = 0;
220 Dbf_entries = 0; /* number of private addresses in dbf file */
222 DEBUG((9,"in get_dbf: "));
223 if (!(dbfilep = fopen(DBFNAME,"r"))) {
224 logmessage(dbfopenmsg);
225 error(E_DBF_IO, EXIT | NOCORE | NO_MSG);
228 while (n = rd_dbf_line(dbfilep,p,&svc_code_p,&flags,&id_p,&res1_p,&res2_p,&res3_p,&private_p,&prognum,&vernum,&module_p,&sflags,&cmd_line_p,NOSUPPRESS)) {
230 if (n == -1) { /* read error */
231 fclose(dbfilep);
232 return(-1);
235 /* make sure service code is legal */
237 i = strlen(svc_code_p);
238 if ( (i == 0) || (i >= SVC_CODE_SZ) )
239 goto reject;
241 /* check for duplicate service code */
242 tdbf_p = dbfhead;
243 while (tdbf_p->dbf_svc_code) { /* duplicate svc code? */
244 if (!strcmp(svc_code_p, tdbf_p->dbf_svc_code)) {
245 sprintf(scratch, dbfdupcmsg, svc_code_p);
246 logmessage(scratch);
247 return(-1);
249 ++tdbf_p;
252 /* NLPS_proc is set by the nlps_server, which also uses these
253 * routines. The actual listener child shouldn't ever need
254 * to read a database, so it will never be here
256 if (!NLPS_proc && (strlen(private_p) == 0) && !(sflags & DFLAG))
257 continue; /* ignore entries with no address */
260 * child doesn't care about private addresses
263 if (!NLPS_proc) {
264 i = strlen(private_p);
265 if (i >= PRV_ADR_SZ) {
266 goto p_reject;
268 Dbf_entries++;
272 * legal, non-duplicate entry: copy it into internal data base
275 dbf_p->dbf_fd = -1; /* set to actual fd in add_prvaddr */
276 dbf_p->dbf_flags = flags;
277 dbf_p->dbf_sflags = sflags;
278 dbf_p->dbf_prognum = prognum;
279 dbf_p->dbf_version = vernum;
280 strcpy(cmd_p, svc_code_p);
281 dbf_p->dbf_svc_code = cmd_p;
282 cmd_p += strlen(svc_code_p) + 1; /* +1 for null */
283 strcpy(cmd_p, cmd_line_p);
284 dbf_p->dbf_cmd_line = cmd_p;
285 cmd_p += strlen(cmd_line_p) + 1;
286 strcpy(cmd_p, id_p);
287 dbf_p->dbf_id = cmd_p;
288 cmd_p += strlen(id_p) + 1;
289 strcpy(cmd_p, res1_p);
290 dbf_p->dbf_res1 = cmd_p;
291 cmd_p += strlen(res1_p) + 1;
292 strcpy(cmd_p, res2_p);
293 dbf_p->dbf_res2 = cmd_p;
294 cmd_p += strlen(res2_p) + 1;
295 strcpy(cmd_p, res3_p);
296 dbf_p->dbf_res3 = cmd_p;
297 cmd_p += strlen(res3_p) + 1;
298 if (strlen(private_p) != 0) {
299 strcpy(cmd_p, private_p);
300 dbf_p->dbf_prv_adr = cmd_p;
301 cmd_p += strlen(private_p) + 1;
303 else
304 dbf_p->dbf_prv_adr = NULL;
305 strcpy(cmd_p, module_p);
306 dbf_p->dbf_modules = cmd_p;
307 cmd_p += strlen(module_p) + 1; /* cmd line + null char */
308 ++dbf_p;
311 fclose(dbfilep);
312 return(0);
314 reject:
315 DEBUG((9, "svc_code <%s> failed validation test", svc_code_p));
316 sprintf(scratch, dbfsvccmsg, svc_code_p);
317 logmessage(scratch);
318 return(-1);
319 p_reject:
320 DEBUG((9,"private address <%s> failed validation test", private_p));
321 sprintf(scratch, "Invalid private address ignored: \\x%x", private_p);
322 logmessage(scratch);
323 return(-1);
328 * scan_dbf: Take a quick pass through the data base file to figure out
329 * approx. how many items in the file we'll need to
330 * allocate storage for. Essentially, returns the number
331 * of non-null, non-comment lines in the data base file.
333 * return: -1 == error.
334 * other == number of non-comment characters.
335 * Dbfentries set.
338 unsigned
339 scan_dbf(path)
340 register char *path;
342 register unsigned int size = 0;
343 register int n;
344 register FILE *dbfilep;
345 char buf[DBFLINESZ];
346 register char *p = buf;
347 char *svc_code_p;
348 int flags;
349 char *cmd_line_p;
350 char *module_p;
351 char *id_p;
352 char *res1_p;
353 char *res2_p;
354 char *res3_p;
355 int sflags;
356 int prognum;
357 int vernum;
358 char *private_p;
359 extern int errno;
361 DEBUG((9, "In scan_dbf. Scanning data base file %s.", path));
363 if (!(dbfilep = fopen(path,"r"))) {
364 DEBUG((9,"errorno = %d", errno));
365 logmessage(dbfopenmsg);
366 return(-1);
369 do {
370 n = rd_dbf_line(dbfilep,p,&svc_code_p,&flags,&id_p,&res1_p,&res2_p,&res3_p,&private_p,&prognum,&vernum,&module_p,&sflags,&cmd_line_p,SUPPRESS);
371 if (n == -1) {
372 fclose(dbfilep);
373 return(-1);
375 size += (unsigned)n;
376 if (n)
377 ++Dbfentries;
378 } while (n);
380 fclose(dbfilep);
381 return(size);
386 * rd_dbf_line: Returns the next non-comment line into the
387 * given buffer (up to DBFLINESZ bytes).
388 * Skips 'ignore' lines.
390 * Returns: 0 = done, -1 = error,
391 * other = cmd line size incl. terminating null.
392 * *svc_code_p = service code;
393 * *id_p = user id string;
394 * *res1_p = reserved string;
395 * *res2_p = reserved string;
396 * *res3_p = reserved string;
397 * *private_p = contains private address;
398 * *flags_p = decoded flags;
399 * prognum = RPC program #;
400 * vernum = RPC version $;
401 * cnd_line_p points to null terminated cmd line;
403 * When logging errors, the extern Dbflineno is used.
407 rd_dbf_line(fp, bp, svc_code_p, flags_p, id_p, res1_p, res2_p, res3_p, private_p, prognum, vernum, module_p, sflags, cmd_line_p, mflag)
408 register FILE *fp;
409 register char *bp;
410 char **svc_code_p;
411 int *flags_p;
412 char **id_p;
413 char **res1_p;
414 char **res2_p;
415 char **res3_p;
416 char **private_p;
417 int *prognum;
418 int *vernum;
419 char **module_p;
420 int *sflags;
421 char **cmd_line_p;
422 int mflag;
424 register int length;
425 register char *p;
427 do {
428 ++Dbflineno;
429 length = 0;
431 if (!fgets(bp, DBFLINESZ, fp)) {
432 if (feof(fp)) {
433 return(0); /* EOF */
435 if (ferror(fp)) {
436 sprintf(bp,dbfrderror,Dbflineno);
437 logmessage(bp);
438 return(-1);
440 sprintf(bp,dbfunknown,Dbflineno);
441 logmessage(bp);
442 return(-1); /* Unknown error (?) */
445 if (*(bp+strlen(bp)-1) != '\n') { /* terminating newline? */
446 sprintf(bp, dbfbadlmsg, Dbflineno);
447 logmessage(bp);
448 return(-1);
451 *(bp + strlen(bp) -1) = '\0'; /* delete newline */
453 if (strlen(bp) && (p = strchr(bp, DBFCOMMENT)))
454 *p = '\0'; /* delete comments */
455 if (!strlen(bp))
456 continue;
458 p = bp + strlen(bp) - 1; /* bp->start; p->end */
459 while ((p != bp) && (isspace(*p))) {
460 *p = '\0'; /* delete terminating spaces */
461 --p;
464 while (*bp) /* del beginning white space*/
465 if (isspace(*bp))
466 ++bp;
467 else
468 break;
470 if (strlen(bp)) { /* anything left? */
472 if (!(length=scan_line(bp,svc_code_p,flags_p,id_p,res1_p,res2_p,res3_p,private_p,prognum,vernum,module_p,sflags,cmd_line_p,mflag))) {
474 DEBUG((1, "rd_dbf_line line %d, error while scanning entry",
475 Dbflineno));
476 sprintf(bp, dbfbadlmsg, Dbflineno);
477 logmessage(bp);
478 return(-1);
482 } while (!length); /* until we have something */
484 DEBUG((5,"rd_dbf_line: line: %d,cmd line len: %d",Dbflineno, length+1));
486 return(length+1); /* +1 for the trailing NULL */
492 * scan a non-white space line
493 * 0 = error;
494 * other = length of cmd line;
496 * non-null lines have the following format:
498 * service_code: flags: id: res1: res2: res3: private address: rpcdata: sflags: modules: cmd_line # comments
500 * mflag is set to suppress messages (scan_line is called both for parsing
501 * and counting, messages should only be output once)
505 scan_line(bp, svc_code_p, flags_p, id_p, res1_p, res2_p, res3_p, private_p, prognum, vernum, module_p, sflags, cmd_line_p, mflag)
506 register char *bp;
507 char **svc_code_p;
508 register int *flags_p;
509 char **id_p;
510 char **res1_p;
511 char **res2_p;
512 char **res3_p;
513 char **private_p;
514 int *prognum;
515 int *vernum;
516 char **module_p;
517 int *sflags;
518 register char **cmd_line_p;
519 int mflag;
521 register char *p;
522 register char *nexttok;
523 register char *ptr;
524 int sawsep = 0;
525 char scratch[BUFSIZ];
527 *flags_p = 0;
529 if (!(p = strchr(bp, DBFTOKSEP ))) { /* look for service code string */
530 DEBUG((9,"scan_line failed svc_code strchr"));
531 return(0);
533 *p = '\0';
534 *svc_code_p = bp;
535 nexttok = ++p;
537 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
538 DEBUG((9,"scan_line failed flags strchr"));
539 return(0);
541 *p = '\0';
543 while (*nexttok) {
544 switch (*nexttok) {
545 case 'x': /* service is turned off */
546 case 'X':
547 *flags_p |= DBF_OFF;
548 break;
549 case 'u': /* create utmp entry */
550 *flags_p |= DBF_UTMP;
551 break;
552 default:
553 DEBUG((1,"scan_line: unknown flag char: 0x%x",*nexttok));
554 *flags_p = DBF_UNKNOWN;
555 break;
557 ++nexttok;
559 nexttok = ++p;
561 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
562 DEBUG((9,"scan_line failed id strchr"));
563 return(0);
565 *p = '\0';
566 *id_p = nexttok;
567 nexttok = ++p;
569 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
570 DEBUG((9,"scan_line failed res1 strchr"));
571 return(0);
573 *p = '\0';
574 *res1_p = nexttok;
575 nexttok = ++p;
577 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
578 DEBUG((9,"scan_line failed res2 strchr"));
579 return(0);
581 *p = '\0';
582 *res2_p = nexttok;
583 nexttok = ++p;
585 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
586 DEBUG((9,"scan_line failed res3 strchr"));
587 return(0);
589 *p = '\0';
590 *res3_p = nexttok;
591 nexttok = ++p;
593 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
594 DEBUG((9,"scan_line failed private strchr"));
595 return(0);
597 *p = '\0';
598 *private_p = nexttok;
599 nexttok = ++p;
601 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
602 DEBUG((9,"scan_line failed rpc strchr"));
603 return(0);
605 *p = '\0';
607 *prognum = -1;
608 *vernum = -1;
609 if (*nexttok) {
610 /* there is rpc info */
611 for (ptr = nexttok; *ptr; ++ptr) {
612 if ((*ptr == ',') && !sawsep) {
614 * skip separator - note that if
615 * separator has been seen, it's not
616 * a digit so it will fail below
618 sawsep++;
619 continue;
621 if (!isdigit(*ptr)) {
622 sprintf(scratch, "service code <%s> specifies non-integer rpc info", *svc_code_p);
623 logmessage(scratch);
624 return(0);
627 ptr = strchr(nexttok, ',');
628 if (ptr) {
629 if ((*prognum = atoi(nexttok)) < 0) {
630 if (!mflag) {
631 /* messages aren't suppressed */
632 sprintf(scratch, "service code <%s> specifies negative program number", *svc_code_p);
633 logmessage(scratch);
635 return(0);
637 if ((*vernum = atoi(ptr + 1)) < 0) {
638 if (!mflag) {
639 sprintf(scratch, "service code <%s> specifies negative version number", *svc_code_p);
640 logmessage(scratch);
642 return(0);
645 else {
646 if (!mflag) {
647 sprintf(scratch, "service code <%s> - invalid rpcinfo", *svc_code_p);
648 logmessage(scratch);
650 return(0);
653 nexttok = ++p;
655 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
656 DEBUG((9,"scan_line failed sflags strchr"));
657 return(0);
659 *p = '\0';
661 *sflags = 0;
662 while (*nexttok) {
663 switch (*nexttok) {
664 case 'c': /* dbf_cmd_line is a command */
665 *sflags |= CFLAG;
666 break;
667 case 'd': /* dynamic address */
668 if ((int) strlen(*private_p) > 0) {
669 if (!mflag) {
670 sprintf(scratch, "service code <%s> specifies static and dynamic address", *svc_code_p);
671 logmessage(scratch);
672 logmessage(" address info ignored");
674 /* don't set DFLAG and wipe out private addr */
675 **private_p = '\0';
677 else {
678 *sflags |= DFLAG;
680 break;
681 case 'p': /* dbf_cmd_line is a pipe */
682 *sflags |= PFLAG;
683 break;
684 default:
685 if (!mflag) {
686 sprintf(scratch, "service code <%s> unknown flag <%c> ignored", *svc_code_p, *nexttok);
687 logmessage(scratch);
689 break;
691 ++nexttok;
693 nexttok = ++p;
695 if (!(p = strchr(nexttok, DBFTOKSEP ))) {
696 DEBUG((9,"scan_line failed module strchr"));
697 return(0);
699 *p = '\0';
700 *module_p = nexttok;
701 nexttok = ++p;
703 *cmd_line_p = nexttok;
705 DEBUG((9,"scan_line: modules: %s; line: %s; len: %d", *module_p, *cmd_line_p, strlen(*svc_code_p)+strlen(*id_p)+strlen(*res1_p)+strlen(*res2_p)+strlen(*res3_p)+strlen(*private_p)+strlen(*module_p)+strlen(*cmd_line_p)+9));
707 * return the length of the buffer. Add 9 for the NULLs after each
708 * string
710 return(strlen(*svc_code_p)+strlen(*id_p)+strlen(*res1_p)+strlen(*res2_p)+strlen(*res3_p)+strlen(*private_p)+strlen(*module_p)+strlen(*cmd_line_p)+9);
715 #define VERSIONSTR "# VERSION="
718 check_version(void)
720 FILE *fp;
721 char *line, *p, *tmp;
722 int version;
724 if ((fp = fopen(DBFNAME, "r")) == NULL) {
725 logmessage(dbfopenmsg);
726 error(E_DBF_IO, EXIT | NOCORE | NO_MSG);
728 if ((line = (char *) malloc(DBFLINESZ)) == NULL)
729 error(E_DBF_ALLOC, EXIT | NOCORE);
730 p = line;
731 while (fgets(p, DBFLINESZ, fp)) {
732 if (!strncmp(p, VERSIONSTR, strlen(VERSIONSTR))) {
733 /* pitch the newline */
734 tmp = strchr(p, '\n');
735 if (tmp)
736 *tmp = '\0';
737 else {
738 logmessage(dbfcorrupt);
739 error(E_DBF_CORRUPT, EXIT | NOCORE);
741 p += strlen(VERSIONSTR);
742 if (*p)
743 version = atoi(p);
744 else {
745 logmessage(dbfcorrupt);
746 error(E_DBF_CORRUPT, EXIT | NOCORE);
748 free(line);
749 fclose(fp);
750 if (version != VERSION)
751 return(1); /* wrong version */
752 else
753 return(0); /* version ok */
755 p = line;
757 logmessage(dbfcorrupt);
758 error(E_DBF_CORRUPT, EXIT | NOCORE);
759 return(1);
764 * mkdbfargv: Given a pointer to a dbf_t, construct argv
765 * for an exec system call.
766 * Warning: returns a pointer to static data which are
767 * overritten by each call.
769 * There is a practical limit of 50 arguments (including argv[0])
771 * Warning: calling mkdbfargv destroys the data (by writing null
772 * characters via strtok) pointed to by dbp->dbf_cmd_line.
775 static char *dbfargv[50];
776 static char *delim = " \t'\""; /* delimiters */
778 char **
779 mkdbfargv(dbp)
780 register dbf_t *dbp;
782 register char **argvp = dbfargv;
783 register char *p = dbp->dbf_cmd_line;
784 char delch;
785 register char *savep;
786 register char *tp;
787 char scratch[BUFSIZ];
788 char *strpbrk();
789 #ifdef DEBUGMODE
790 register int i = 0;
791 #endif
793 *argvp = 0;
794 savep = p;
795 while (p && *p) {
796 if (p = strpbrk(p, delim)) {
797 switch (*p) {
798 case ' ':
799 case '\t':
800 /* "normal" cases */
801 *p++ = '\0';
802 *argvp++ = savep;
803 DEBUG((9, "argv[%d] = %s", i++, savep));
804 /* zap trailing white space */
805 while (isspace(*p))
806 p++;
807 savep = p;
808 break;
809 case '"':
810 case '\'':
811 /* found a string */
812 delch = *p; /* remember the delimiter */
813 savep = ++p;
816 * We work the string in place, embedded instances of the string delimiter,
817 * i.e. \" must have the '\' removed. Since we'd have to do a compare to
818 * decide if a copy were needed, it's less work to just do the copy, even
819 * though it is most likely unnecessary.
822 tp = p;
823 for (;;) {
824 if (*p == '\0') {
825 sprintf(scratch, "invalid command line, non-terminated string for service code %s", dbp->dbf_svc_code);
826 logmessage(scratch);
827 exit(2); /* server, don't log */
829 if (*p == delch) {
830 if (*(tp - 1) == '\\') { /* \delim */
831 *(tp - 1) = *p;
832 p++;
834 else { /* end of string */
835 *tp = 0;
836 *argvp++ = savep;
837 DEBUG((9, "argv[%d] = %s", i++, savep));
838 p++;
839 /* zap trailing white space */
840 while (isspace(*p))
841 p++;
842 savep = p;
843 break;
846 else {
847 *tp++ = *p++;
850 break;
851 default:
852 logmessage("Internal error in parse routine");
853 exit(2); /* server, don't log */
856 else {
857 *argvp++ = savep;
858 DEBUG((9, "argv[%d] = %s", i++, savep));
861 *argvp = 0;
862 return(dbfargv);
869 * getentry: Given a fd, this routine will return a
870 * dbf entry. If the entry doesn't exist it will
871 * return NULL.
874 dbf_t *
875 getentry(fd)
876 int fd;
878 extern dbf_t *Dbfhead; /* Dbfentries (when allocated) */
879 register dbf_t *dbp = Dbfhead;
881 if (!Dbfhead) { /* no private address in database file */
882 DEBUG((9, "getdbfentry - nothing in Dbfhead = %s ",Dbfhead));
883 return((dbf_t *)0);
885 else
886 for (dbp = Dbfhead; dbp->dbf_prv_adr; ++dbp)
887 if (fd == dbp->dbf_fd) {
888 return(dbp);
891 return((dbf_t *)0); /* requested private address not in list */
897 * pushmod: push modules if defined in the data base entry.
899 * WARNING: This routine writes into the in-memory copy
900 * of the database file. Therefore, after it is called,
901 * the incore copy of the database file will no longer be valid.
905 pushmod(fd, mp)
906 int fd;
907 register char *mp;
909 register char *cp;
910 register char *bufp = mp;
911 char name[32];
912 extern int errno;
914 DEBUG((9,"in pushmod:"));
915 if (!mp || *mp == '\0') {
916 DEBUG((9,"NULL list: exiting pushmod"));
917 return(0);
919 /* pop timod if it is on the stack */
920 if (ioctl(fd, I_LOOK, name) >= 0) {
921 if (strcmp(name, "timod") == 0) {
922 if (ioctl(fd, I_POP, 0) < 0)
923 DEBUG((9,"pushmod: I_POP failed"));
926 while ((cp = strtok(bufp, ",")) != NULL) {
927 bufp = NULL;
928 DEBUG((9,"pushmod: about to push %s", cp));
929 if (ioctl(fd, I_PUSH, cp) < 0) {
930 DEBUG((9,"pushmod: ioctl failed, errno = %d",errno));
931 return(1);
934 DEBUG((9,"exiting pushmod:"));
935 return(0);