free(saveset);
setmode(const char *p){	int perm, who;	char op, *ep;	BITCMD *set, *saveset, *endset;	sigset_t sigset, sigoset;	mode_t mask;	int equalopdone, permXbits, setlen;	u_long perml;	if (!*p)		return (NULL);	/*	 * Get a copy of the mask for the permissions that are mask relative.	 * Flip the bits, we want what's not set.  Since it's possible that	 * the caller is opening files inside a signal handler, protect them	 * as best we can.	 */	sigfillset(&sigset);	(void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);	(void)umask(mask = umask(0));	mask = ~mask;	(void)sigprocmask(SIG_SETMASK, &sigoset, NULL);	setlen = SET_LEN + 2;		if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)		return (NULL);	saveset = set;	endset = set + (setlen - 2);	/*	 * If an absolute number, get it and return; disallow non-octal digits	 * or illegal bits.	 */	if (isdigit(*p)) {		perml = strtoul(p, &ep, 8);		/* The test on perml will also catch overflow. */		if (*ep != '\0' || (perml & ~(STANDARD_BITS|S_ISTXT))) {			errno = ERANGE;			free(saveset);			return (NULL);		}		perm = (mode_t)perml;		ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);		set->cmd = 0;		return (saveset);	}	/*	 * Build list of structures to set/clear/copy bits as described by	 * each clause of the symbolic mode.	 */	for (;;) {		/* First, find out which bits might be modified. */		for (who = 0;; ++p) {			switch (*p) {			case 'a':				who |= STANDARD_BITS;				break;			case 'u':				who |= S_ISUID|S_IRWXU;				break;			case 'g':				who |= S_ISGID|S_IRWXG;				break;			case 'o':				who |= S_IRWXO;				break;			default:				goto getop;			}		}getop:		if ((op = *p++) != '+' && op != '-' && op != '=') {			free(saveset);			return (NULL);		}		if (op == '=')			equalopdone = 0;		who &= ~S_ISTXT;		for (perm = 0, permXbits = 0;; ++p) {			switch (*p) {			case 'r':				perm |= S_IRUSR|S_IRGRP|S_IROTH;				break;			case 's':				/*				 * If specific bits where requested and				 * only "other" bits ignore set-id.				 */				if (who == 0 || (who & ~S_IRWXO))					perm |= S_ISUID|S_ISGID;				break;			case 't':				/*				 * If specific bits where requested and				 * only "other" bits ignore sticky.				 */				if (who == 0 || (who & ~S_IRWXO)) {					who |= S_ISTXT;					perm |= S_ISTXT;				}				break;			case 'w':				perm |= S_IWUSR|S_IWGRP|S_IWOTH;				break;			case 'X':				permXbits = S_IXUSR|S_IXGRP|S_IXOTH;				break;			case 'x':				perm |= S_IXUSR|S_IXGRP|S_IXOTH;				break;			case 'u':			case 'g':			case 'o':				/*				 * When ever we hit 'u', 'g', or 'o', we have				 * to flush out any partial mode that we have,				 * and then do the copying of the mode bits.				 */				if (perm) {					ADDCMD(op, who, perm, mask);					perm = 0;				}				if (op == '=')					equalopdone = 1;				if (op == '+' && permXbits) {					ADDCMD('X', who, permXbits, mask);					permXbits = 0;				}				ADDCMD(*p, who, op, mask);				break;			default:				/*				 * Add any permissions that we haven't already				 * done.				 */				if (perm || (op == '=' && !equalopdone)) {					if (op == '=')						equalopdone = 1;					ADDCMD(op, who, perm, mask);					perm = 0;				}				if (permXbits) {					ADDCMD('X', who, permXbits, mask);					permXbits = 0;				}				goto apply;			}		}apply:		if (!*p)			break;		if (*p != ',')			goto getop;		++p;	}	set->cmd = 0;#ifdef SETMODE_DEBUG	(void)printf("Before compress_mode()\n");	dumpmode(saveset);#endif	compress_mode(saveset);#ifdef SETMODE_DEBUG	(void)printf("After compress_mode()\n");	dumpmode(saveset);#endif	return (saveset);}