4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2017 Peter Tribble.
27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
43 #include <sys/types.h>
48 #include "pkglibmsgs.h"
49 #include "pkglocale.h"
51 #define ERR_CANT_READ_LCLPATH "unable to read local pathname"
52 #define ERR_BAD_VOLUME_NUMBER "bad volume number"
53 #define ERR_CANNOT_READ_PATHNAME_FIELD "unable to read pathname field"
54 #define ERR_CANNOT_READ_CONTENT_INFO "unable to read content info"
55 #define ERR_EXTRA_TOKENS_PRESENT "extra tokens on input line"
56 #define ERR_CANNOT_READ_CLASS_TOKEN "unable to read class token"
57 #define ERR_BAD_LINK_SPEC "missing or invalid link specification"
58 #define ERR_UNKNOWN_FTYPE "unknown ftype"
59 #define ERR_NO_LINKSOURCE "no link source specified"
60 #define ERR_CANNOT_READ_MM_DEVNUMS "unable to read major/minor "\
62 static int eatwhite(FILE *fp
);
63 static int getend(FILE *fp
);
64 static int getstr(FILE *fp
, char *sep
, int n
, char *str
);
65 static int getnum(FILE *fp
, int base
, long *d
, long bad
);
66 static int getlnum(FILE *fp
, int base
, fsblkcnt_t
*d
, long bad
);
67 static int getvalmode(FILE *fp
, mode_t
*d
, long bad
, int map
);
69 static int getendvfp(char **cp
);
70 static void findendvfp(char **cp
);
71 static int getstrvfp(char **cp
, char *sep
, int n
, char *str
);
72 static int getvalmodevfp(char **cp
, mode_t
*d
, long bad
, int map
);
73 int getnumvfp(char **cp
, int base
, long *d
, long bad
);
74 int getlnumvfp(char **cp
, int base
, fsblkcnt_t
*d
, long bad
);
76 static char mypath
[PATH_MAX
];
77 static char mylocal
[PATH_MAX
];
78 static int mapmode
= MAPNONE
;
79 static char *maptype
= "";
80 static mode_t d_mode
= BADMODE
;
81 static char *d_owner
= BADOWNER
;
82 static char *d_group
= BADGROUP
;
85 * These determine how gpkgmap() deals with mode, owner and group defaults.
86 * It is assumed that the owner and group arguments represent static fields
87 * which will persist until attrdefault() is called.
90 attrpreset(int mode
, char *owner
, char *group
)
106 * This determines how gpkgmap() deals with environment variables in the
107 * mode, owner and group. Path is evaluated at a higher level based upon
108 * other circumstances.
113 if (mode
>= 0 || mode
<= 3) {
115 if (mode
== MAPBUILD
)
117 else if (mode
== MAPINSTALL
)
118 maptype
= " install";
124 /* This is the external query interface for mapmode. */
132 * Unpack the pkgmap or the contents file or whatever file is in that format.
133 * Based upon mapmode, environment parameters will be resolved for mode,
138 gpkgmap(struct cfent
*ept
, FILE *fp
)
141 boolean_t first_char
= B_TRUE
;
145 ept
->ftype
= BADFTYPE
;
146 (void) strcpy(ept
->pkg_class
, BADCLASS
);
147 ept
->pkg_class_idx
= -1;
149 ept
->ainfo
.local
= NULL
;
150 /* default attributes were supplied, so don't reset */
151 ept
->ainfo
.mode
= d_mode
;
152 (void) strcpy(ept
->ainfo
.owner
, d_owner
);
153 (void) strcpy(ept
->ainfo
.group
, d_group
);
154 ept
->ainfo
.major
= BADMAJOR
;
155 ept
->ainfo
.minor
= BADMINOR
;
156 ept
->cinfo
.cksum
= ept
->cinfo
.modtime
= ept
->cinfo
.size
= (-1L);
166 * If the first character is not a digit, we assume that the
167 * volume number is 1.
169 if (first_char
&& !isdigit(c
)) {
172 first_char
= B_FALSE
;
189 setErrstr(pkg_gt(ERR_BAD_VOLUME_NUMBER
));
193 ept
->volno
= (ept
->volno
*10)+c
-'0';
195 } while (isdigit(c
));
207 * Since we are going to scan the next line,
208 * we need to reset volume number and first_char.
215 ept
->ftype
= (char)c
;
220 (void) ungetc(c
, fp
);
222 if (getstr(fp
, "=", PATH_MAX
, mypath
)) {
223 setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD
));
229 if (getstr(fp
, NULL
, PATH_MAX
, mylocal
)) {
230 setErrstr(pkg_gt(ERR_CANT_READ_LCLPATH
));
233 ept
->ainfo
.local
= mylocal
;
235 (void) ungetc(c
, fp
);
237 if (ept
->ftype
== 'i') {
238 /* content info might exist */
239 if (!getlnum(fp
, 10, (fsblkcnt_t
*)&ept
->cinfo
.size
,
241 (getnum(fp
, 10, (long *)&ept
->cinfo
.cksum
,
243 getnum(fp
, 10, (long *)&ept
->cinfo
.modtime
,
245 setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO
));
250 setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT
));
266 ept
->ftype
= (char)c
;
267 if (getstr(fp
, NULL
, CLSSIZ
, ept
->pkg_class
)) {
268 setErrstr(pkg_gt(ERR_CANNOT_READ_CLASS_TOKEN
));
271 if (getstr(fp
, "=", PATH_MAX
, mypath
)) {
272 setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD
));
280 if (getstr(fp
, NULL
, PATH_MAX
, mylocal
)) {
281 if (ept
->ftype
== 's' || ept
->ftype
== 'l') {
282 setErrstr(pkg_gt(ERR_READLINK
));
285 pkg_gt(ERR_CANT_READ_LCLPATH
));
289 ept
->ainfo
.local
= mylocal
;
290 } else if (strchr("sl", ept
->ftype
)) {
291 if ((c
!= EOF
) && (c
!= '\n'))
293 setErrstr(pkg_gt(ERR_BAD_LINK_SPEC
));
296 (void) ungetc(c
, fp
);
300 setErrstr(pkg_gt(ERR_UNKNOWN_FTYPE
));
306 if (strchr("sl", ept
->ftype
) && (ept
->ainfo
.local
== NULL
)) {
307 setErrstr(pkg_gt(ERR_NO_LINKSOURCE
));
311 if (strchr("cb", ept
->ftype
)) {
312 ept
->ainfo
.major
= BADMAJOR
;
313 ept
->ainfo
.minor
= BADMINOR
;
314 if (getnum(fp
, 10, (long *)&ept
->ainfo
.major
, BADMAJOR
) ||
315 getnum(fp
, 10, (long *)&ept
->ainfo
.minor
, BADMINOR
)) {
316 setErrstr(pkg_gt(ERR_CANNOT_READ_MM_DEVNUMS
));
322 * Links and information files don't have attributes associated with
323 * them. The following either resolves potential variables or passes
324 * them through. Mode is tested for validity to some degree. BAD???
325 * is returned to indicate that no meaningful mode was provided. A
326 * higher authority will decide if that's OK or not. CUR??? means that
327 * the prototype file specifically requires a wildcard ('?') for
328 * that entry. We issue an error if attributes were entered wrong.
329 * We just return BAD??? if there was no entry at all.
331 if (strchr("cbdxpfve", ept
->ftype
)) {
334 if ((retval
= getvalmode(fp
, &(ept
->ainfo
.mode
), CURMODE
,
335 (mapmode
!= MAPNONE
))) == 1)
336 goto end
; /* nothing else on the line */
337 else if (retval
== 2)
338 goto error
; /* mode is too no good */
340 /* owner & group should be here */
341 if ((retval
= getstr(fp
, NULL
, ATRSIZ
,
342 ept
->ainfo
.owner
)) == 1)
343 goto end
; /* no owner or group - warning */
345 setErrstr(pkg_gt(ERR_OWNTOOLONG
));
349 if ((retval
= getstr(fp
, NULL
, ATRSIZ
,
350 ept
->ainfo
.group
)) == 1)
351 goto end
; /* no group - warning */
353 setErrstr(pkg_gt(ERR_GRPTOOLONG
));
357 /* Resolve the parameters if required. */
358 if (mapmode
!= MAPNONE
) {
359 if (mapvar(mapmode
, ept
->ainfo
.owner
)) {
360 (void) snprintf(getErrbufAddr(),
363 maptype
, ept
->ainfo
.owner
);
364 setErrstr(getErrbufAddr());
367 if (mapvar(mapmode
, ept
->ainfo
.group
)) {
368 (void) snprintf(getErrbufAddr(),
369 getErrbufSize(), pkg_gt(ERR_NOVAR
),
370 maptype
, ept
->ainfo
.group
);
371 setErrstr(getErrbufAddr());
377 if (strchr("ifve", ept
->ftype
)) {
378 /* look for content description */
379 if (!getlnum(fp
, 10, (fsblkcnt_t
*)&ept
->cinfo
.size
, BADCONT
) &&
380 (getnum(fp
, 10, (long *)&ept
->cinfo
.cksum
, BADCONT
) ||
381 getnum(fp
, 10, (long *)&ept
->cinfo
.modtime
, BADCONT
))) {
382 setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO
));
387 if (ept
->ftype
== 'i')
391 if (getend(fp
) && ept
->pinfo
) {
392 setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT
));
400 * Get and validate the mode attribute. This returns an error if
401 * 1. the mode string is too long
402 * 2. the mode string includes alpha characters
403 * 3. the mode string is not octal
404 * 4. mode string is an install parameter
405 * 5. mode is an unresolved build parameter and MAPBUILD is
407 * If the mode is a build parameter, it is
408 * 1. returned as is if MAPNONE is in effect
409 * 2. evaluated if MAPBUILD is in effect
411 * NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
412 * time. At install time we just fix a mode with bad bits set by
413 * setting it to CURMODE. This should be an error in a few releases
414 * (2.8 maybe) but faulty modes are so common in existing packages
415 * that this is a reasonable exception. -- JST 1994-11-9
418 * 0 if mode is being returned as a valid value
419 * 1 if no attributes are present on the line
420 * 2 if there was a fundamental error
423 getvalmode(FILE *fp
, mode_t
*d
, long bad
, int map
)
429 if ((retval
= getstr(fp
, NULL
, ATRSIZ
, tempmode
)) == 1)
431 else if (retval
== -1) {
432 setErrstr(pkg_gt(ERR_MODELONG
));
436 * If it isn't a '?' (meaning go with whatever mode is
437 * there), validate the mode and convert it to a mode_t. The
438 * "bad" variable here is a misnomer. It doesn't necessarily
441 if (tempmode
[0] == '?') {
445 * Mode may not be an install parameter or a
446 * non-build parameter.
448 if (tempmode
[0] == '$' &&
449 (isupper(tempmode
[1]) || !islower(tempmode
[1]))) {
450 setErrstr(pkg_gt(ERR_IMODE
));
454 if ((map
) && (mapvar(mapmode
, tempmode
))) {
455 (void) snprintf(getErrbufAddr(),
459 setErrstr(getErrbufAddr());
464 if (tempmode
[0] == '$') {
465 *d
= BADMODE
; /* may be a problem */
468 * At this point it's supposed to be
469 * something we can convert to a number.
474 * We reject it if it contains nonnumbers or
477 while (tempmode
[n
] && !isspace(tempmode
[n
])) {
478 if (!isdigit(tempmode
[n
])) {
480 pkg_gt(ERR_MODEALPHA
));
484 if (strchr("89abcdefABCDEF",
487 pkg_gt(ERR_BASEINVAL
));
493 tempmode_t
= strtol(tempmode
, NULL
, 8);
496 * We reject it if it contains inappropriate
499 if (tempmode_t
& ~(S_IAMB
|
500 S_ISUID
| S_ISGID
| S_ISVTX
)) {
501 if (mapmode
!= MAPBUILD
) {
504 setErrstr(pkg_gt(ERR_MODEBITS
));
516 getnum(FILE *fp
, int base
, long *d
, long bad
)
520 /* leading white space ignored */
527 if ((c
== EOF
) || (c
== '\n') || !isdigit(c
)) {
528 (void) ungetc(c
, fp
);
537 *d
= (*d
* base
) + b
;
540 (void) ungetc(c
, fp
);
545 getlnum(FILE *fp
, int base
, fsblkcnt_t
*d
, long bad
)
549 /* leading white space ignored */
556 if ((c
== EOF
) || (c
== '\n') || !isdigit(c
)) {
557 (void) ungetc(c
, fp
);
566 *d
= (*d
* base
) + b
;
569 (void) ungetc(c
, fp
);
574 * Get a string from the file. Returns
577 * -1 if string is too long
580 getstr(FILE *fp
, char *sep
, int n
, char *str
)
584 /* leading white space ignored */
586 if ((c
== EOF
) || (c
== '\n')) {
587 (void) ungetc(c
, fp
);
588 return (1); /* nothing there */
591 /* fill up string until space, tab, or separator */
592 while (!strchr(" \t", c
) && (!sep
|| !strchr(sep
, c
))) {
595 return (-1); /* too long */
599 if ((c
== EOF
) || (c
== '\n'))
600 break; /* no more on this line */
603 (void) ungetc(c
, fp
);
616 if ((c
= getc(fp
)) == EOF
)
629 /* this test works around a side effect of getc() */
634 while ((c
== ' ') || (c
== '\t'));
639 gpkgmapvfp(struct cfent
*ept
, VFP_T
*vfp
)
642 boolean_t first_char
= B_TRUE
;
643 (void) strlcpy(ept
->pkg_class
, BADCLASS
, sizeof (ept
->pkg_class
));
644 (void) strlcpy(ept
->ainfo
.owner
, d_owner
, sizeof (ept
->ainfo
.owner
));
645 (void) strlcpy(ept
->ainfo
.group
, d_group
, sizeof (ept
->ainfo
.group
));
649 ept
->ftype
= BADFTYPE
;
650 ept
->pkg_class_idx
= -1;
652 ept
->ainfo
.local
= NULL
;
653 ept
->ainfo
.mode
= d_mode
;
654 ept
->ainfo
.major
= BADMAJOR
;
655 ept
->ainfo
.minor
= BADMINOR
;
656 ept
->cinfo
.cksum
= (-1L);
657 ept
->cinfo
.modtime
= (-1L);
658 ept
->cinfo
.size
= (-1L);
662 /* return error if no vfp specified */
664 if (vfp
== (VFP_T
*)NULL
) {
669 while (((c
= vfpGetcNoInc(vfp
)) != '\0') && (isspace(vfpGetc(vfp
))))
673 * If the first character is not a digit, we assume that the
674 * volume number is 1.
676 if (first_char
&& !isdigit(c
)) {
679 first_char
= B_FALSE
;
682 * In case of hsfs the zero-padding of partial pages
683 * returned by mmap is not done properly. A separate bug has been filed
687 if (vfp
->_vfpCurr
&& (vfp
->_vfpCurr
> vfp
->_vfpEnd
)) {
706 setErrstr(pkg_gt(ERR_BAD_VOLUME_NUMBER
));
710 ept
->volno
= (ept
->volno
*10)+c
-'0';
712 } while (isdigit(c
));
713 if (ept
->volno
== 0) {
721 (void) findendvfp(&vfpGetCurrCharPtr(vfp
));
725 * Since we are going to scan the next line,
726 * we need to reset volume number and first_char.
733 ept
->ftype
= (char)c
;
734 while (((c
= vfpGetcNoInc(vfp
)) != '\0') &&
735 (isspace(vfpGetc(vfp
))))
742 if (getstrvfp(&vfpGetCurrCharPtr(vfp
), "=", PATH_MAX
, mypath
)) {
743 setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD
));
749 if (getstrvfp(&vfpGetCurrCharPtr(vfp
), NULL
, PATH_MAX
,
751 setErrstr(pkg_gt(ERR_CANT_READ_LCLPATH
));
754 ept
->ainfo
.local
= mylocal
;
759 if (ept
->ftype
== 'i') {
760 /* content info might exist */
761 if (!getlnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
762 (fsblkcnt_t
*)&ept
->cinfo
.size
, BADCONT
) &&
763 (getnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
764 (long *)&ept
->cinfo
.cksum
, BADCONT
) ||
765 getnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
766 (long *)&ept
->cinfo
.modtime
, BADCONT
))) {
767 setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO
));
772 if (getendvfp(&vfpGetCurrCharPtr(vfp
))) {
773 setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT
));
789 ept
->ftype
= (char)c
;
790 if (getstrvfp(&vfpGetCurrCharPtr(vfp
), NULL
,
791 CLSSIZ
, ept
->pkg_class
)) {
792 setErrstr(pkg_gt(ERR_CANNOT_READ_CLASS_TOKEN
));
795 if (getstrvfp(&vfpGetCurrCharPtr(vfp
), "=", PATH_MAX
, mypath
)) {
796 setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD
));
804 if (getstrvfp(&vfpGetCurrCharPtr(vfp
), NULL
,
805 PATH_MAX
, mylocal
)) {
806 if (ept
->ftype
== 's' || ept
->ftype
== 'l') {
807 setErrstr(pkg_gt(ERR_READLINK
));
810 pkg_gt(ERR_CANT_READ_LCLPATH
));
814 ept
->ainfo
.local
= mylocal
;
815 } else if ((ept
->ftype
== 's') || (ept
->ftype
== 'l')) {
816 if ((c
!= '\0') && (c
!= '\n'))
817 (void) findendvfp(&vfpGetCurrCharPtr(vfp
));
818 setErrstr(pkg_gt(ERR_BAD_LINK_SPEC
));
826 setErrstr(pkg_gt(ERR_UNKNOWN_FTYPE
));
828 (void) findendvfp(&vfpGetCurrCharPtr(vfp
));
832 if (((ept
->ftype
== 's') || (ept
->ftype
== 'l')) &&
833 (ept
->ainfo
.local
== NULL
)) {
834 setErrstr(pkg_gt(ERR_NO_LINKSOURCE
));
838 if (((ept
->ftype
== 'c') || (ept
->ftype
== 'b'))) {
839 ept
->ainfo
.major
= BADMAJOR
;
840 ept
->ainfo
.minor
= BADMINOR
;
842 if (getnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
843 (long *)&ept
->ainfo
.major
, BADMAJOR
) ||
844 getnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
845 (long *)&ept
->ainfo
.minor
, BADMINOR
)) {
846 setErrstr(pkg_gt(ERR_CANNOT_READ_MM_DEVNUMS
));
852 * Links and information files don't have attributes associated with
853 * them. The following either resolves potential variables or passes
854 * them through. Mode is tested for validity to some degree. BAD???
855 * is returned to indicate that no meaningful mode was provided. A
856 * higher authority will decide if that's OK or not. CUR??? means that
857 * the prototype file specifically requires a wildcard ('?') for
858 * that entry. We issue an error if attributes were entered wrong.
859 * We just return BAD??? if there was no entry at all.
861 if ((ept
->ftype
== 'd') || (ept
->ftype
== 'x') || (ept
->ftype
== 'c') ||
862 (ept
->ftype
== 'b') || (ept
->ftype
== 'p') ||
863 (ept
->ftype
== 'f') || (ept
->ftype
== 'v') ||
864 (ept
->ftype
== 'e')) {
867 retval
= getvalmodevfp(&vfpGetCurrCharPtr(vfp
),
869 CURMODE
, (mapmode
!= MAPNONE
));
872 goto end
; /* nothing else on the line */
873 } else if (retval
== 2) {
874 goto error
; /* mode is too no good */
877 /* owner & group should be here */
878 if ((retval
= getstrvfp(&vfpGetCurrCharPtr(vfp
), NULL
, ATRSIZ
,
879 ept
->ainfo
.owner
)) == 1)
880 goto end
; /* no owner or group - warning */
882 setErrstr(pkg_gt(ERR_OWNTOOLONG
));
886 if ((retval
= getstrvfp(&vfpGetCurrCharPtr(vfp
), NULL
, ATRSIZ
,
887 ept
->ainfo
.group
)) == 1)
888 goto end
; /* no group - warning */
890 setErrstr(pkg_gt(ERR_GRPTOOLONG
));
894 /* Resolve the parameters if required. */
895 if (mapmode
!= MAPNONE
) {
896 if (mapvar(mapmode
, ept
->ainfo
.owner
)) {
897 (void) snprintf(getErrbufAddr(),
898 getErrbufSize(), pkg_gt(ERR_NOVAR
),
899 maptype
, ept
->ainfo
.owner
);
900 setErrstr(getErrbufAddr());
903 if (mapvar(mapmode
, ept
->ainfo
.group
)) {
904 (void) snprintf(getErrbufAddr(),
905 getErrbufSize(), pkg_gt(ERR_NOVAR
),
906 maptype
, ept
->ainfo
.group
);
907 setErrstr(getErrbufAddr());
913 if ((ept
->ftype
== 'i') || (ept
->ftype
== 'f') ||
914 (ept
->ftype
== 'v') || (ept
->ftype
== 'e')) {
915 /* look for content description */
916 if (!getlnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
917 (fsblkcnt_t
*)&ept
->cinfo
.size
, BADCONT
) &&
918 (getnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
919 (long *)&ept
->cinfo
.cksum
, BADCONT
) ||
920 getnumvfp(&vfpGetCurrCharPtr(vfp
), 10,
921 (long *)&ept
->cinfo
.modtime
, BADCONT
))) {
922 setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO
));
927 if (ept
->ftype
== 'i')
931 if (getendvfp(&vfpGetCurrCharPtr(vfp
)) && ept
->pinfo
) {
932 setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT
));
940 * Get and validate the mode attribute. This returns an error if
941 * 1. the mode string is too long
942 * 2. the mode string includes alpha characters
943 * 3. the mode string is not octal
944 * 4. mode string is an install parameter
945 * 5. mode is an unresolved build parameter and MAPBUILD is
947 * If the mode is a build parameter, it is
948 * 1. returned as is if MAPNONE is in effect
949 * 2. evaluated if MAPBUILD is in effect
951 * NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
952 * time. At install time we just fix a mode with bad bits set by
953 * setting it to CURMODE. This should be an error in a few releases
954 * (2.8 maybe) but faulty modes are so common in existing packages
955 * that this is a reasonable exception. -- JST 1994-11-9
958 * 0 if mode is being returned as a valid value
959 * 1 if no attributes are present on the line
960 * 2 if there was a fundamental error
963 getvalmodevfp(char **cp
, mode_t
*d
, long bad
, int map
)
965 char tempmode
[ATRSIZ
+1];
970 if ((retval
= getstrvfp(cp
, NULL
, sizeof (tempmode
), tempmode
)) == 1) {
972 } else if (retval
== -1) {
973 setErrstr(pkg_gt(ERR_MODELONG
));
978 * If it isn't a '?' (meaning go with whatever mode is
979 * there), validate the mode and convert it to a mode_t. The
980 * "bad" variable here is a misnomer. It doesn't necessarily
983 if (tempmode
[0] == '?') {
989 * Mode may not be an install parameter or a
990 * non-build parameter.
993 if (tempmode
[0] == '$' &&
994 (isupper(tempmode
[1]) || !islower(tempmode
[1]))) {
995 setErrstr(pkg_gt(ERR_IMODE
));
999 if ((map
) && (mapvar(mapmode
, tempmode
))) {
1000 (void) snprintf(getErrbufAddr(), getErrbufSize(),
1001 pkg_gt(ERR_NOVAR
), maptype
, tempmode
);
1002 setErrstr(getErrbufAddr());
1006 if (tempmode
[0] == '$') {
1007 *d
= BADMODE
; /* may be a problem */
1011 /* it's supposed to be something we can convert to a number */
1015 /* reject it if it contains nonnumbers or it's not octal */
1017 while (tempmode
[n
] && !isspace(tempmode
[n
])) {
1018 if (!isdigit(tempmode
[n
])) {
1019 setErrstr(pkg_gt(ERR_MODEALPHA
));
1023 if (strchr("89abcdefABCDEF", tempmode
[n
])) {
1024 setErrstr(pkg_gt(ERR_BASEINVAL
));
1030 tempmode_t
= strtol(tempmode
, NULL
, 8);
1033 * We reject it if it contains inappropriate
1036 if (tempmode_t
& (~(S_IAMB
| S_ISUID
| S_ISGID
| S_ISVTX
))) {
1037 if (mapmode
== MAPBUILD
) {
1038 setErrstr(pkg_gt(ERR_MODEBITS
));
1050 getnumvfp(char **cp
, int base
, long *d
, long bad
)
1059 /* leading white space ignored */
1060 while (((c
= *p
) != '\0') && (isspace(*p
++)))
1068 if ((c
== '\0') || (c
== '\n') || !isdigit(c
)) {
1075 while (isdigit(c
)) {
1076 *d
= (*d
* base
) + (c
& 017);
1085 getlnumvfp(char **cp
, int base
, fsblkcnt_t
*d
, long bad
)
1094 /* leading white space ignored */
1095 while (((c
= *p
) != '\0') && (isspace(*p
++)))
1103 if ((c
== '\0') || (c
== '\n') || !isdigit(c
)) {
1110 while (isdigit(c
)) {
1111 *d
= (*d
* base
) + (c
& 017);
1120 getstrvfp(char **cp
, char *sep
, int n
, char *str
)
1132 /* leading white space ignored */
1134 while (((c
= *p
) != '\0') && (isspace(*p
++)))
1136 if ((c
== '\0') || (c
== '\n')) {
1139 return (1); /* nothing there */
1144 /* generate complete list of delimiters to scan for */
1146 (void) strlcpy(delims
, " \t\n", sizeof (delims
));
1147 if ((sep
!= (char *)NULL
) && (*sep
!= '\0')) {
1148 (void) strlcat(delims
, sep
, sizeof (delims
));
1151 /* compute length based on delimiter found or not */
1153 p1
= strpbrk(p
, delims
);
1154 if (p1
== (char *)NULL
) {
1157 len
= (ptrdiff_t)p1
- (ptrdiff_t)p
;
1160 /* if string will fit in result buffer copy string and return success */
1163 (void) memcpy(str
, p
, len
);
1170 /* result buffer too small; copy partial string, return error */
1171 (void) memcpy(str
, p
, n
-1);
1180 * Description: Locate the end of the current line given a pointer into a buffer
1181 * containing characters that is null terminated.
1182 * Arguments: char **cp - pointer to pointer to null-terminated string buffer
1183 * Returns: int == 0 -- no non-space characters preceeded the newline
1184 * != 0 -- one or more non-space characters preceeded newline
1185 * Effects: cp is updated to point to the first character PAST the first new
1186 * line character found. If no newline character is found, cp is
1187 * updated to point to the '\0' at the end of the buffer.
1191 getendvfp(char **cp
)
1198 /* if at end of buffer return no more characters left */
1204 /* find the first null or end of line character */
1206 while ((*p
!= '\0') && (*p
!= '\n')) {
1215 /* if at newline, increment pointer to first character past newline */
1221 /* set return pointer to null or first character past newline */
1225 /* return space/nospace indicator */
1232 * Description: Locate the end of the current line given a pointer into a buffer
1233 * containing characters that is null terminated.
1234 * Arguments: char **cp - pointer to pointer to null-terminated string buffer
1236 * Effects: cp is updated to point to the first character PAST the first new
1237 * line character found. If no newline character is found, cp is
1238 * updated to point to the '\0' at the end of the buffer.
1242 findendvfp(char **cp
)
1247 /* if at end of buffer return no more characters left */
1253 /* find the end of the line */
1255 p1
= strchr(p
, '\n');
1256 if (p1
!= (char *)NULL
) {
1261 /* no newline found - point to null terminator */
1263 *cp
= strchr(p
, '\0');