1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 29 #include <stdio.h> 30 #include <sys/types.h> 31 #include <sys/resource.h> 32 #include <string.h> 33 #include <signal.h> 34 #include <limits.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <time.h> 40 #include <locale.h> 41 #include <libintl.h> 42 #include <ctype.h> 43 #include <pkglib.h> 44 #include <libinst.h> 45 46 #define ERR_SET_ULIMIT "unable to set ulimit to <%ld> blocks" 47 #define ERR_DO_ULIMIT "An attempt was made to create a file larger than " \ 48 "ULIMIT. Source of fault is unknown." 49 #define ERR_SCRULIMIT "Script <%s> attempted to create a file exceeding " \ 50 "ULIMIT." 51 52 static char *script_name = NULL, *scr_error = NULL; 53 static struct rlimit ulimit = {RLIM_INFINITY, RLIM_INFINITY}; 54 static struct rlimit dblimit = {RLIM_INFINITY, RLIM_INFINITY}; 55 static int limit_is_set = 0, fail_return = 0; 56 57 void ulimit_quit(); /* XFSZ controlled signal handler. */ 58 int clr_ulimit(); /* Clear the user supplied file size limit. */ 59 void set_limit(); /* Called from installf to undo ulimit */ 60 int set_ulimit(char *script, char *err_msg); 61 int assign_ulimit(char *fslimit); 62 63 extern int warnflag; 64 65 void 66 set_limit() 67 { 68 limit_is_set = 1; 69 } 70 71 int 72 clr_ulimit() 73 { 74 if (limit_is_set) { 75 if (script_name) 76 free(script_name); 77 script_name = NULL; 78 if (scr_error) 79 free(scr_error); 80 scr_error = NULL; 81 fail_return = 99; 82 83 /* Clear out the limit to infinity. */ 84 return (setrlimit(RLIMIT_FSIZE, &dblimit)); 85 } else 86 return (0); 87 } 88 89 /* 90 * This sets up the ULIMIT facility for the signal retrieval. This sets up 91 * the static pointers to the message constants for indicating where the 92 * error occurred. 93 */ 94 int 95 set_ulimit(char *script, char *err_msg) 96 { 97 int n; 98 99 if (limit_is_set) { 100 (void) signal(SIGXFSZ, ulimit_quit); 101 if (script_name) 102 free(script_name); 103 script_name = strdup(script); 104 if (scr_error) 105 free(scr_error); 106 scr_error = strdup(err_msg); 107 fail_return = 99; 108 109 n = setrlimit(RLIMIT_FSIZE, &ulimit); 110 111 return (n); 112 } else 113 return (0); 114 115 } 116 117 /* Validate ULIMIT and set accordingly. */ 118 int 119 assign_ulimit(char *fslimit) 120 { 121 rlim_t limit; 122 int cnt = 0; 123 124 if (fslimit && *fslimit) { 125 /* fslimit must be a simple unsigned integer. */ 126 do { 127 if (!isdigit(fslimit[cnt])) 128 return (-1); 129 } while (fslimit[++cnt]); 130 131 limit = atol(fslimit); 132 133 ulimit.rlim_cur = (limit * 512); /* fslimit is in blocks */ 134 135 limit_is_set = 1; 136 137 return (0); 138 } else 139 return (-1); 140 } 141 142 /* 143 * This is the signal handler for ULIMIT. 144 */ 145 void 146 ulimit_quit(int n) 147 { 148 #ifdef lint 149 int i = n; 150 n = i; 151 #endif /* lint */ 152 153 setrlimit(RLIMIT_FSIZE, &dblimit); 154 signal(SIGXFSZ, SIG_IGN); 155 156 if (script_name) { 157 progerr(gettext(ERR_SCRULIMIT), script_name); 158 if (scr_error) 159 progerr("%s", scr_error); 160 } else 161 progerr(gettext(ERR_DO_ULIMIT)); 162 163 quit(fail_return); 164 } 165