8672 proc_t changes broke genunix dmods and walker
[unleashed.git] / usr / src / cmd / passmgmt / passmgmt.c
blob2b4f34e8db7c28184d5c8ba304fe28d18db933eb
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <shadow.h>
31 #include <pwd.h>
32 #include <string.h>
33 #include <signal.h>
34 #include <sys/stat.h>
35 #include <errno.h>
36 #include <time.h>
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <locale.h>
40 #include <fcntl.h>
41 #include <secdb.h>
42 #include <user_attr.h>
43 #include <nss.h>
45 #define CMT_SIZE (128+1) /* Argument sizes + 1 (for '\0') */
46 #define DIR_SIZE (256+1)
47 #define SHL_SIZE (256+1)
48 #define ENTRY_LENGTH 512 /* Max length of an /etc/passwd entry */
49 #define UID_MIN 100 /* Lower bound of default UID */
51 #define M_MASK 01 /* Masks for the optn_mask variable */
52 #define L_MASK 02 /* It keeps track of which options */
53 #define C_MASK 04 /* have been entered */
54 #define H_MASK 010
55 #define U_MASK 020
56 #define G_MASK 040
57 #define S_MASK 0100
58 #define O_MASK 0200
59 #define A_MASK 0400
60 #define D_MASK 01000
61 #define F_MASK 02000
62 #define E_MASK 04000
64 #define UATTR_MASK 010000
66 /* flags for info_mask */
67 #define LOGNAME_EXIST 01 /* logname exists */
68 #define BOTH_FILES 02 /* touch both password files */
69 #define WRITE_P_ENTRY 04 /* write out password entry */
70 #define WRITE_S_ENTRY 010 /* write out shadow entry */
71 #define NEED_DEF_UID 020 /* need default uid */
72 #define FOUND 040 /* found the entry in password file */
73 #define LOCKED 0100 /* did we lock the password file */
74 #define UATTR_FILE 0200 /* touch user_attr file */
75 #define BAD_ENT_MESSAGE "%s: Bad entry found in /etc/passwd. Run pwconv.\n"
77 typedef struct kvopts {
78 const char option;
79 const char *key;
80 char *newvalue;
81 } kvopts_t;
83 /* mapping of extensible keywords and options */
84 kvopts_t ua_opts[] = {
85 { 'A', USERATTR_AUTHS_KW },
86 { 'P', USERATTR_PROFILES_KW },
87 { 'R', USERATTR_ROLES_KW },
88 { 'T', USERATTR_TYPE_KW },
89 { '\0', USERATTR_DEFAULTPROJ_KW },
90 { '\0', USERATTR_LIMPRIV_KW },
91 { '\0', USERATTR_DFLTPRIV_KW },
92 { '\0', USERATTR_LOCK_AFTER_RETRIES_KW },
93 { '\0', USERATTR_LABELVIEW },
94 { '\0', USERATTR_CLEARANCE },
95 { '\0', USERATTR_MINLABEL },
96 { '\0', USERATTR_AUDIT_FLAGS_KW },
99 #define UA_KEYS (sizeof (ua_opts)/sizeof (kvopts_t))
102 char defdir[] = "/home/"; /* default home directory for new user */
103 char pwdflr[] = "x"; /* password string for /etc/passwd */
104 char lkstring[] = "*LK*"; /* lock string for shadow password */
105 char nullstr[] = ""; /* null string */
106 char *msg; /* pointer to error message */
108 #define DATMSK "DATEMSK=/etc/datemsk"
110 #define OUSERATTR_FILENAME "/etc/ouser_attr"
111 #define USERATTR_TEMP "/etc/uatmp"
113 struct uid_blk {
114 struct uid_blk *link;
115 uid_t low; /* low bound for this uid block */
116 uid_t high; /* high bound for this uid block */
119 extern userattr_t *fgetuserattr(FILE *);
123 * Declare all functions that do not return integers. This is here
124 * to get rid of some lint messages
127 void uid_bcom(struct uid_blk *), add_ublk(uid_t, struct uid_blk *),
128 bad_perm(void),
129 bad_usage(char *), bad_arg(char *), bad_uid(void), bad_pasf(void),
130 file_error(void), bad_news(void), no_lock(void), add_uid(uid_t),
131 rid_tmpf(void), ck_p_sz(struct passwd *), ck_s_sz(struct spwd *),
132 bad_name(char *), bad_uattr(void);
134 void file_copy(FILE *spf, long NIS_pos);
136 static FILE *fp_ptemp, *fp_stemp, *fp_uatemp;
137 static int fd_ptemp, fd_stemp, fd_uatemp;
140 * The uid_blk structure is used in the search for the default
141 * uid. Each uid_blk represent a range of uid(s) that are currently
142 * used on the system.
146 #ifndef att
148 * getspnan routine that ONLY looks at the local shadow file
150 struct spwd *
151 local_getspnam(char *name)
153 FILE *shadf;
154 struct spwd *sp;
156 if ((shadf = fopen("/etc/shadow", "r")) == NULL)
157 return (NULL);
159 while ((sp = fgetspent(shadf)) != NULL) {
160 if (strcmp(sp->sp_namp, name) == 0)
161 break;
164 fclose(shadf);
166 return (sp);
168 #endif
170 static void
171 putuserattrent(userattr_t *user, FILE *f)
173 int i, j;
174 char *key;
175 char *val;
176 kv_t *kv_pair;
179 * Avoid trivial entries. Those with no attributes or with
180 * only "type=normal". This retains backward compatibility.
182 if (user->attr == NULL)
183 return;
185 kv_pair = user->attr->data;
187 for (i = j = 0; i < user->attr->length; i++) {
188 key = kv_pair[i].key;
189 val = kv_pair[i].value;
190 if ((key == NULL) || (val == NULL))
191 break;
192 if (strlen(val) == 0 ||
193 (strcmp(key, USERATTR_TYPE_KW) == 0 &&
194 strcmp(val, USERATTR_TYPE_NORMAL_KW) == 0))
195 continue;
196 j++;
198 if (j == 0)
199 return;
201 (void) fprintf(f, "%s:%s:%s:%s:", user->name, user->qualifier,
202 user->res1, user->res2);
204 for (i = j = 0; i < user->attr->length; i++) {
205 key = kv_pair[i].key;
206 val = _escape(kv_pair[i].value, KV_SPECIAL);
207 if ((key == NULL) || (val == NULL))
208 break;
209 if (strlen(val) == 0)
210 continue;
211 if (j > 0)
212 (void) fprintf(f, KV_DELIMITER);
213 (void) fprintf(f, "%s=%s", key, val);
214 j++;
216 (void) fprintf(f, "\n");
219 static void
220 assign_attr(userattr_t *user, const char *newkey, char *val)
223 int i;
224 char *key;
225 kv_t *kv_pair;
226 int avail = -1;
228 if (user->attr != NULL) {
229 kv_pair = user->attr->data;
230 for (i = 0; i < user->attr->length; i++) {
231 key = kv_pair[i].key;
232 if (key == NULL) {
233 avail = i;
234 continue;
235 } else if (strcmp(key, newkey) == 0) {
236 kv_pair[i].value = strdup(val);
237 return;
241 if (avail == -1)
242 avail = user->attr->length++;
243 kv_pair[avail].key = strdup(newkey);
244 kv_pair[avail].value = strdup(val);
248 static void
249 unassign_role(userattr_t *user, char *rolelist, char *role)
252 char *roleptr;
253 char *templist;
254 char *temprole;
255 int length;
257 roleptr = rolelist;
258 templist = strdup(roleptr);
259 temprole = strtok(templist, ",");
260 while (temprole) {
261 if (strcmp(temprole, role) == 0) {
263 length = strlen(role);
264 roleptr += temprole - templist;
266 if (*(roleptr + length) == ',')
267 length++;
268 strcpy(roleptr, roleptr + length);
269 length = strlen(roleptr) - 1;
270 if (*(roleptr + length) == ',')
271 *(roleptr + length) = '\0';
272 assign_attr(user, USERATTR_ROLES_KW, rolelist);
273 break;
274 } else {
275 temprole = strtok(NULL, ",");
280 struct uid_blk *uid_sp;
281 char *prognamp; /* program name */
282 extern int errno;
283 int optn_mask = 0, info_mask = 0;
284 extern int getdate_err;
287 main(int argc, char **argv)
289 int c, i;
290 char *lognamp, *char_p;
291 int end_of_file = 0;
292 int error;
293 long date = 0;
294 FILE *pwf, *spf, *uaf;
296 struct passwd *pw_ptr1p, passwd_st;
297 struct spwd *sp_ptr1p, shadow_st;
298 userattr_t *ua_ptr1p, userattr_st;
299 static kv_t ua_kv[KV_ADD_KEYS];
300 kva_t ua_kva;
301 struct stat statbuf;
302 struct tm *tm_ptr;
303 int NIS_entry_seen; /* NIS scanning flag */
305 * NIS start pos, really pointer to first entry AFTER first
306 * NIS-referant entry
308 long NIS_pos;
309 long cur_pos; /* Current pos, used with nis-pos above */
311 (void) setlocale(LC_ALL, "");
313 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
314 #define TEXT_DOMAIN "SYS_TEST"
315 #endif
316 (void) textdomain(TEXT_DOMAIN);
318 tzset();
319 /* Get program name */
320 prognamp = argv[0];
322 /* Check identity */
323 if (geteuid() != 0)
324 bad_perm();
326 /* Lock the password file(s) */
328 if (lckpwdf() != 0)
329 no_lock();
330 info_mask |= LOCKED; /* remember we locked */
332 /* initialize the two structures */
334 passwd_st.pw_passwd = pwdflr; /* bogus password */
335 passwd_st.pw_name = nullstr; /* login name */
336 passwd_st.pw_uid = -1; /* no uid */
337 passwd_st.pw_gid = 1; /* default gid */
338 passwd_st.pw_age = nullstr; /* no aging info. */
339 passwd_st.pw_comment = nullstr; /* no comments */
340 passwd_st.pw_gecos = nullstr; /* no comments */
341 passwd_st.pw_dir = nullstr; /* no default directory */
342 passwd_st.pw_shell = nullstr; /* no default shell */
344 shadow_st.sp_namp = nullstr; /* no name */
345 shadow_st.sp_pwdp = lkstring; /* locked password */
346 shadow_st.sp_lstchg = -1; /* no lastchanged date */
347 shadow_st.sp_min = -1; /* no min */
348 shadow_st.sp_max = -1; /* no max */
349 shadow_st.sp_warn = -1; /* no warn */
350 shadow_st.sp_inact = -1; /* no inactive */
351 shadow_st.sp_expire = -1; /* no expire */
352 shadow_st.sp_flag = 0; /* no flag */
354 userattr_st.name = nullstr;
355 userattr_st.qualifier = nullstr;
356 userattr_st.res1 = nullstr;
357 userattr_st.res2 = nullstr;
359 ua_kva.length = 1;
360 ua_kv[0].key = USERATTR_TYPE_KW;
361 ua_kv[0].value = USERATTR_TYPE_NORMAL_KW;
362 ua_kva.data = ua_kv;
363 userattr_st.attr = &ua_kva;
365 /* parse the command line */
367 while ((c = getopt(argc, argv,
368 "ml:c:h:u:g:s:f:e:k:A:P:R:T:oadK:")) != -1) {
370 switch (c) {
371 case 'm':
372 /* Modify */
374 if ((A_MASK|D_MASK|M_MASK) & optn_mask)
375 bad_usage("Invalid combination of options");
377 optn_mask |= M_MASK;
378 break;
380 case 'l' :
381 /* Change logname */
383 if ((A_MASK|D_MASK|L_MASK) & optn_mask)
384 bad_usage("Invalid combination of options");
386 if (strpbrk(optarg, ":\n") ||
387 strlen(optarg) == 0)
388 bad_arg("Invalid argument to option -l");
390 optn_mask |= L_MASK;
391 passwd_st.pw_name = optarg;
392 shadow_st.sp_namp = optarg;
393 userattr_st.name = optarg;
394 break;
396 case 'f' :
397 /* set inactive */
399 if ((D_MASK|F_MASK) & optn_mask)
400 bad_usage("Invalid combination of options");
401 if (((shadow_st.sp_inact =
402 strtol(optarg, &char_p, 10)) < (long)0) ||
403 (*char_p != '\0') ||
404 strlen(optarg) == 0)
405 bad_arg("Invalid argument to option -f");
406 if (shadow_st.sp_inact == 0)
407 shadow_st.sp_inact = -1;
408 optn_mask |= F_MASK;
409 break;
411 case 'e' :
412 /* set expire date */
414 if ((D_MASK|E_MASK) & optn_mask)
415 bad_usage("Invalid combination of options");
417 if ((strlen(optarg)) < (size_t)2)
418 shadow_st.sp_expire = -1;
419 else {
420 putenv(DATMSK);
421 if ((tm_ptr = getdate(optarg)) == NULL) {
422 msg = "Invalid argument to option -e";
423 bad_arg(msg);
425 if ((date = mktime(tm_ptr)) < 0) {
426 msg = "Invalid argument to option -e";
427 bad_arg(msg);
429 shadow_st.sp_expire = (date / DAY);
430 if (shadow_st.sp_expire <= DAY_NOW) {
431 msg = "Invalid argument to option -e";
432 bad_arg(msg);
436 optn_mask |= E_MASK;
437 break;
439 case 'c' :
440 /* The comment */
442 if ((D_MASK|C_MASK) & optn_mask)
443 bad_usage("Invalid combination of options");
445 if (strlen(optarg) > (size_t)CMT_SIZE ||
446 strpbrk(optarg, ":\n"))
447 bad_arg("Invalid argument to option -c");
449 optn_mask |= C_MASK;
450 passwd_st.pw_comment = optarg;
451 passwd_st.pw_gecos = optarg;
452 break;
454 case 'h' :
455 /* The home directory */
457 if ((D_MASK|H_MASK) & optn_mask)
458 bad_usage("Invalid combination of options");
460 if (strlen(optarg) > (size_t)DIR_SIZE ||
461 strpbrk(optarg, ":\n"))
462 bad_arg("Invalid argument to option -h");
464 optn_mask |= H_MASK;
465 passwd_st.pw_dir = optarg;
466 break;
468 case 'u' :
469 /* The uid */
471 if ((D_MASK|U_MASK) & optn_mask)
472 bad_usage("Invalid combination of options");
474 optn_mask |= U_MASK;
475 passwd_st.pw_uid = (uid_t)strtol(optarg, &char_p, 10);
476 if ((*char_p != '\0') ||
477 (passwd_st.pw_uid < 0) ||
478 (strlen(optarg) == 0))
479 bad_arg("Invalid argument to option -u");
481 break;
483 case 'g' :
484 /* The gid */
486 if ((D_MASK|G_MASK) & optn_mask)
487 bad_usage("Invalid combination of options");
489 optn_mask |= G_MASK;
490 passwd_st.pw_gid = (gid_t)strtol(optarg, &char_p, 10);
492 if ((*char_p != '\0') || (passwd_st.pw_gid < 0) ||
493 (strlen(optarg) == 0))
494 bad_arg("Invalid argument to option -g");
495 break;
497 case 's' :
498 /* The shell */
500 if ((D_MASK|S_MASK) & optn_mask)
501 bad_usage("Invalid combination of options");
503 if (strlen(optarg) > (size_t)SHL_SIZE ||
504 strpbrk(optarg, ":\n"))
505 bad_arg("Invalid argument to option -s");
507 optn_mask |= S_MASK;
508 passwd_st.pw_shell = optarg;
509 break;
511 case 'o' :
512 /* Override unique uid */
514 if ((D_MASK|O_MASK) & optn_mask)
515 bad_usage("Invalid combination of options");
517 optn_mask |= O_MASK;
518 break;
520 case 'a' :
521 /* Add */
523 if ((A_MASK|M_MASK|D_MASK|L_MASK) & optn_mask)
524 bad_usage("Invalid combination of options");
526 optn_mask |= A_MASK;
527 break;
529 case 'd' :
530 /* Delete */
532 if ((D_MASK|M_MASK|L_MASK|C_MASK|
533 H_MASK|U_MASK|G_MASK|S_MASK|
534 O_MASK|A_MASK) & optn_mask)
535 bad_usage("Invalid combination of options");
537 optn_mask |= D_MASK;
538 break;
540 case 'K':
541 if (D_MASK & optn_mask)
542 bad_usage("Invalid combination of options");
544 char_p = strchr(optarg, '=');
545 if (char_p == NULL)
546 bad_usage("Missing value in -K option");
548 *char_p++ = '\0';
550 for (i = 0; i < UA_KEYS; i++) {
551 if (strcmp(optarg, ua_opts[i].key) == 0) {
552 ua_opts[i].newvalue =
553 _escape(char_p, KV_SPECIAL);
554 assign_attr(&userattr_st, optarg,
555 char_p);
556 break;
559 if (i == UA_KEYS)
560 bad_usage("bad key");
561 optn_mask |= UATTR_MASK;
562 break;
564 case '?' :
566 bad_usage("");
567 break;
569 default :
570 /* Extended User Attributes */
572 int j;
574 for (j = 0; j < UA_KEYS; j++) {
575 if (ua_opts[j].option == (char)c) {
576 if ((D_MASK) & optn_mask)
577 bad_usage("Invalid "
578 "combination of "
579 " options");
580 optn_mask |= UATTR_MASK;
581 assign_attr(&userattr_st,
582 ua_opts[j].key,
583 _escape(optarg,
584 KV_SPECIAL));
585 ua_opts[j].newvalue =
586 _escape(optarg, KV_SPECIAL);
587 break;
590 break;
595 /* check command syntax for the following errors */
596 /* too few or too many arguments */
597 /* no -a -m or -d option */
598 /* -o without -u */
599 /* -m with no other option */
601 if (optind == argc || argc > (optind+1) ||
602 !((A_MASK|M_MASK|D_MASK) & optn_mask) ||
603 ((optn_mask & O_MASK) && !(optn_mask & U_MASK)) ||
604 ((optn_mask & M_MASK) &&
605 !(optn_mask &
606 (L_MASK|C_MASK|H_MASK|U_MASK|G_MASK|S_MASK|F_MASK|
607 E_MASK|UATTR_MASK))))
608 bad_usage("Invalid command syntax");
610 /* null string argument or bad characters ? */
611 if ((strlen(argv[optind]) == 0) || strpbrk(argv[optind], ":\n"))
612 bad_arg("Invalid name");
614 lognamp = argv [optind];
617 * if we are adding a new user or modifying an existing user
618 * (not the logname), then copy logname into the two data
619 * structures
622 if ((A_MASK & optn_mask) ||
623 ((M_MASK & optn_mask) && !(optn_mask & L_MASK))) {
624 passwd_st.pw_name = argv [optind];
625 shadow_st.sp_namp = argv [optind];
626 userattr_st.name = argv [optind];
629 /* Put in directory if we are adding and we need a default */
631 if (!(optn_mask & H_MASK) && (optn_mask & A_MASK)) {
632 if ((passwd_st.pw_dir = malloc((size_t)DIR_SIZE)) == NULL)
633 file_error();
635 *passwd_st.pw_dir = '\0';
636 (void) strcat(passwd_st.pw_dir, defdir);
637 (void) strcat(passwd_st.pw_dir, lognamp);
640 /* Check the number of password files we are touching */
642 if ((!((M_MASK & optn_mask) && !(L_MASK & optn_mask))) ||
643 ((M_MASK & optn_mask) && ((E_MASK & optn_mask) ||
644 (F_MASK & optn_mask))))
645 info_mask |= BOTH_FILES;
647 if ((D_MASK|L_MASK|UATTR_MASK) & optn_mask)
648 info_mask |= UATTR_FILE;
650 /* Open the temporary file(s) with appropriate permission mask */
651 /* and the appropriate owner */
653 if (stat(PASSWD, &statbuf) < 0)
654 file_error();
656 fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
657 if (fd_ptemp == -1) {
658 if (errno == EEXIST) {
659 if (unlink(PASSTEMP)) {
660 msg = "%s: warning: cannot unlink %s\n";
661 (void) fprintf(stderr, gettext(msg), prognamp,
662 PASSTEMP);
664 fd_ptemp = open(PASSTEMP, O_CREAT|O_EXCL|O_WRONLY,
665 statbuf.st_mode);
666 if (fd_ptemp == -1) {
667 file_error();
670 } else
671 file_error();
673 fp_ptemp = fdopen(fd_ptemp, "w");
674 if (fp_ptemp == NULL)
675 file_error();
676 error = fchown(fd_ptemp, statbuf.st_uid, statbuf.st_gid);
677 if (error == 0)
678 error = fchmod(fd_ptemp, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
679 if (error != 0) {
680 (void) fclose(fp_ptemp);
681 if (unlink(PASSTEMP)) {
682 msg = "%s: warning: cannot unlink %s\n";
683 (void) fprintf(stderr, gettext(msg), prognamp,
684 PASSTEMP);
686 file_error();
689 if (info_mask & BOTH_FILES) {
690 if (stat(SHADOW, &statbuf) < 0) {
691 rid_tmpf();
692 file_error();
694 fd_stemp = open(SHADTEMP, O_CREAT|O_EXCL|O_WRONLY,
695 statbuf.st_mode);
696 if (fd_stemp == -1) {
697 if (errno == EEXIST) {
698 if (unlink(SHADTEMP)) {
699 msg = "%s: warning: cannot unlink %s\n";
700 (void) fprintf(stderr, gettext(msg),
701 prognamp, SHADTEMP);
703 fd_stemp = open(SHADTEMP,
704 O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
705 if (fd_stemp == -1) {
706 rid_tmpf();
707 file_error();
710 } else {
711 rid_tmpf();
712 file_error();
715 fp_stemp = fdopen(fd_stemp, "w");
716 if (fp_stemp == NULL) {
717 rid_tmpf();
718 file_error();
720 error = fchown(fd_stemp, statbuf.st_uid, statbuf.st_gid);
721 if (error == 0)
722 error = fchmod(fd_stemp, S_IRUSR);
723 if (error != 0) {
724 rid_tmpf();
725 file_error();
729 if (info_mask & UATTR_FILE) {
730 if (stat(USERATTR_FILENAME, &statbuf) < 0) {
731 rid_tmpf();
732 file_error();
734 fd_uatemp = open(USERATTR_TEMP, O_CREAT|O_EXCL|O_WRONLY,
735 statbuf.st_mode);
736 if (fd_uatemp == -1) {
737 if (errno == EEXIST) {
738 if (unlink(USERATTR_TEMP)) {
739 msg = "%s: warning: cannot unlink %s\n";
740 (void) fprintf(stderr, gettext(msg),
741 prognamp, USERATTR_TEMP);
743 fd_uatemp = open(USERATTR_TEMP,
744 O_CREAT|O_EXCL|O_WRONLY, statbuf.st_mode);
745 if (fd_uatemp == -1) {
746 rid_tmpf();
747 file_error();
750 } else {
751 rid_tmpf();
752 file_error();
755 fp_uatemp = fdopen(fd_uatemp, "w");
756 if (fp_uatemp == NULL) {
757 rid_tmpf();
758 file_error();
760 error = fchown(fd_uatemp, statbuf.st_uid, statbuf.st_gid);
761 if (error == 0)
762 error = fchmod(fd_uatemp,
763 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
764 if (error != 0) {
765 rid_tmpf();
766 file_error();
769 /* Default uid needed ? */
771 if (!(optn_mask & U_MASK) && (optn_mask & A_MASK)) {
772 /* mark it in the information mask */
773 info_mask |= NEED_DEF_UID;
775 /* create the head of the uid number list */
776 uid_sp = malloc(sizeof (struct uid_blk));
777 if (uid_sp == NULL) {
778 rid_tmpf();
779 file_error();
782 uid_sp->link = NULL;
783 uid_sp->low = (UID_MIN -1);
784 uid_sp->high = (UID_MIN -1);
788 * This next section is modified to allow for NIS passwd file
789 * conventions. In the case where a password entry was being
790 * added to the password file, the original AT&T code read
791 * the entire password file in, noted any information needed, and
792 * copied the entries to a temporary file. Then the new entry
793 * was added to the temporary file, and the temporary file was
794 * moved to be the real password file.
796 * The problem is, that with NIS compatability, we want to add new
797 * entries BEFORE the first NIS-referrant entry, so as not to have
798 * any surprises. To accomplish this without extensively modifying
799 * the logic of the code below, as soon as a NIS-referrant entry is
800 * found we stop copying entries to the TEMP file and instead we
801 * remember
802 * the first NIS entry and where we found it, scan the rest of the
803 * password file without copying entries, then write the new entry, copy
804 * the stored password entry, then copy the rest of the password file.
808 error = 0;
810 if ((pwf = fopen("/etc/passwd", "r")) == NULL) {
811 rid_tmpf();
812 if (errno == ENOENT)
813 bad_news();
814 else
815 file_error();
818 NIS_entry_seen = 0;
819 cur_pos = 0;
820 /* The while loop for reading PASSWD entries */
821 info_mask |= WRITE_P_ENTRY;
823 while (!end_of_file) {
824 pw_ptr1p = fgetpwent(pwf);
825 if (pw_ptr1p == NULL) {
826 if (!feof(pwf)) {
827 /* A real error - report it and exit */
828 rid_tmpf();
829 bad_pasf();
831 else
832 break;
835 if (!NIS_entry_seen)
836 info_mask |= WRITE_P_ENTRY;
837 else
838 info_mask &= ~WRITE_P_ENTRY;
841 * Set up the uid usage blocks to find the first
842 * available uid above UID_MIN, if needed
845 if (info_mask & NEED_DEF_UID)
846 add_uid(pw_ptr1p->pw_uid);
848 /* Check for unique UID */
850 if (strcmp(lognamp, pw_ptr1p->pw_name) &&
851 (pw_ptr1p->pw_uid == passwd_st.pw_uid) &&
852 ((optn_mask & U_MASK) && !(optn_mask & O_MASK))) {
853 rid_tmpf(); /* get rid of temp files */
854 bad_uid();
857 /* Check for unique new logname */
859 if (strcmp(lognamp, pw_ptr1p->pw_name) == 0 &&
860 optn_mask & L_MASK &&
861 strcmp(pw_ptr1p->pw_name, passwd_st.pw_name) == 0) {
862 rid_tmpf();
863 #ifdef att
864 if (!getspnam(pw_ptr1p->pw_name))
865 #else
866 if (!local_getspnam(pw_ptr1p->pw_name))
867 #endif
868 bad_pasf();
869 else
870 bad_name("logname already exists");
873 if (strcmp(lognamp, pw_ptr1p->pw_name) == 0) {
875 /* no good if we want to add an existing logname */
876 if (optn_mask & A_MASK) {
877 rid_tmpf();
878 #ifdef att
879 if (!getspnam(lognamp))
880 #else
881 if (!local_getspnam(lognamp))
882 #endif
883 bad_pasf();
884 else
885 bad_name("name already exists");
888 /* remember we found it */
889 info_mask |= FOUND;
891 /* Do not write it out on the fly */
892 if (optn_mask & D_MASK)
893 info_mask &= ~WRITE_P_ENTRY;
895 if (optn_mask & M_MASK) {
897 #ifdef att
898 if (!getspnam(lognamp))
899 #else
900 if (!local_getspnam(lognamp))
901 #endif
903 rid_tmpf();
904 bad_pasf();
906 if (optn_mask & L_MASK)
907 pw_ptr1p->pw_name = passwd_st.pw_name;
909 if (optn_mask & U_MASK)
910 pw_ptr1p->pw_uid = passwd_st.pw_uid;
912 if (optn_mask & G_MASK)
913 pw_ptr1p->pw_gid = passwd_st.pw_gid;
915 if (optn_mask & C_MASK) {
916 pw_ptr1p->pw_comment =
917 passwd_st.pw_comment;
919 pw_ptr1p->pw_gecos =
920 passwd_st.pw_comment;
923 if (optn_mask & H_MASK)
924 pw_ptr1p->pw_dir = passwd_st.pw_dir;
926 if (optn_mask & S_MASK)
927 pw_ptr1p->pw_shell = passwd_st.pw_shell;
928 ck_p_sz(pw_ptr1p); /* check entry size */
932 if (optn_mask & A_MASK) {
933 if (!NIS_entry_seen) {
934 char *p;
935 p = strchr("+-", pw_ptr1p->pw_name[0]);
936 if (p != NULL) {
938 * Found first NIS entry.
939 * so remember it.
941 NIS_pos = cur_pos;
942 NIS_entry_seen = 1;
943 info_mask &= ~WRITE_P_ENTRY;
945 else
946 cur_pos = ftell(pwf);
950 if (info_mask & WRITE_P_ENTRY) {
951 if (putpwent(pw_ptr1p, fp_ptemp)) {
952 rid_tmpf();
953 file_error();
956 } /* end-of-while-loop */
958 if (error >= 1) {
959 msg = "%s: Bad entry found in /etc/passwd. Run pwconv.\n";
960 fprintf(stderr, gettext(msg), prognamp);
963 /* Cannot find the target entry and we are deleting or modifying */
965 if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) {
966 rid_tmpf();
967 #ifdef att
968 if (getspnam(lognamp) != NULL)
969 #else
970 if (local_getspnam(lognamp) != NULL)
971 #endif
972 bad_pasf();
973 else
974 bad_name("name does not exist");
977 /* First available uid above UID_MIN is ... */
979 if (info_mask & NEED_DEF_UID)
980 passwd_st.pw_uid = uid_sp->high + 1;
982 /* Write out the added entry now */
984 if (optn_mask & A_MASK) {
985 ck_p_sz(&passwd_st); /* Check entry size */
986 if (putpwent(&passwd_st, fp_ptemp)) {
987 rid_tmpf();
988 file_error();
991 * Now put out the rest of the password file, if needed.
993 if (NIS_entry_seen) {
994 int n;
995 char buf[1024];
997 if (fseek(pwf, NIS_pos, SEEK_SET) < 0) {
998 rid_tmpf();
999 file_error();
1001 while ((n = fread(buf, sizeof (char), 1024, pwf)) > 0) {
1002 if (fwrite(buf, sizeof (char), n, fp_ptemp)
1003 != n) {
1004 rid_tmpf();
1005 file_error();
1011 (void) fclose(pwf);
1013 /* flush and sync the file before closing it */
1014 if (fflush(fp_ptemp) != 0 || fsync(fd_ptemp) != 0)
1015 file_error();
1017 /* Now we are done with PASSWD */
1018 (void) fclose(fp_ptemp);
1020 /* Do this if we are touching both password files */
1023 if (info_mask & BOTH_FILES) {
1024 info_mask &= ~FOUND; /* Reset FOUND flag */
1026 /* The while loop for reading SHADOW entries */
1027 info_mask |= WRITE_S_ENTRY;
1029 end_of_file = 0;
1030 errno = 0;
1031 error = 0;
1033 NIS_entry_seen = 0;
1034 cur_pos = 0;
1036 if ((spf = fopen("/etc/shadow", "r")) == NULL) {
1037 rid_tmpf();
1038 file_error();
1041 while (!end_of_file) {
1042 sp_ptr1p = fgetspent(spf);
1043 if (sp_ptr1p == NULL) {
1044 if (!feof(spf)) {
1045 rid_tmpf();
1046 bad_pasf();
1048 else
1049 break;
1052 if (!NIS_entry_seen)
1053 info_mask |= WRITE_S_ENTRY;
1054 else
1055 info_mask &= ~WRITE_S_ENTRY;
1058 * See if the new logname already exist in the
1059 * shadow passwd file
1061 if ((optn_mask & M_MASK) &&
1062 strcmp(lognamp, shadow_st.sp_namp) != 0 &&
1063 strcmp(sp_ptr1p->sp_namp, shadow_st.sp_namp) == 0) {
1064 rid_tmpf();
1065 bad_pasf();
1068 if (strcmp(lognamp, sp_ptr1p->sp_namp) == 0) {
1069 info_mask |= FOUND;
1070 if (optn_mask & A_MASK) {
1071 /* password file inconsistent */
1072 rid_tmpf();
1073 bad_pasf();
1076 if (optn_mask & M_MASK) {
1077 sp_ptr1p->sp_namp = shadow_st.sp_namp;
1078 if (F_MASK & optn_mask)
1079 sp_ptr1p->sp_inact =
1080 shadow_st.sp_inact;
1081 if (E_MASK & optn_mask)
1082 sp_ptr1p->sp_expire =
1083 shadow_st.sp_expire;
1085 ck_s_sz(sp_ptr1p);
1088 if (optn_mask & D_MASK)
1089 info_mask &= ~WRITE_S_ENTRY;
1092 if (optn_mask & A_MASK) {
1093 if (!NIS_entry_seen) {
1094 char *p;
1095 p = strchr("+-", sp_ptr1p->sp_namp[0]);
1096 if (p != NULL) {
1098 * Found first NIS entry.
1099 * so remember it.
1101 NIS_pos = cur_pos;
1102 NIS_entry_seen = 1;
1103 info_mask &= ~WRITE_S_ENTRY;
1105 else
1106 cur_pos = ftell(spf);
1110 if (info_mask & WRITE_S_ENTRY) {
1111 if (putspent(sp_ptr1p, fp_stemp)) {
1112 rid_tmpf();
1113 file_error();
1117 } /* end-of-while-loop */
1119 if (error >= 1) {
1121 msg = BAD_ENT_MESSAGE;
1122 fprintf(stderr, gettext(msg), prognamp);
1126 * If we cannot find the entry and we are deleting or
1127 * modifying
1130 if (!(info_mask & FOUND) && (optn_mask & (D_MASK|M_MASK))) {
1131 rid_tmpf();
1132 bad_pasf();
1135 if (optn_mask & A_MASK) {
1136 ck_s_sz(&shadow_st);
1137 if (putspent(&shadow_st, fp_stemp)) {
1138 rid_tmpf();
1139 file_error();
1143 * Now put out the rest of the shadow file, if needed.
1145 if (NIS_entry_seen) {
1146 file_copy(spf, NIS_pos);
1150 /* flush and sync the file before closing it */
1151 if (fflush(fp_stemp) != 0 || fsync(fd_stemp) != 0)
1152 file_error();
1153 (void) fclose(fp_stemp);
1155 /* Done with SHADOW */
1156 (void) fclose(spf);
1158 } /* End of if info_mask */
1160 if (info_mask & UATTR_FILE) {
1161 info_mask &= ~FOUND; /* Reset FOUND flag */
1163 /* The while loop for reading USER_ATTR entries */
1164 info_mask |= WRITE_S_ENTRY;
1166 end_of_file = 0;
1167 errno = 0;
1168 error = 0;
1170 NIS_entry_seen = 0;
1171 cur_pos = 0;
1173 if ((uaf = fopen(USERATTR_FILENAME, "r")) == NULL) {
1174 rid_tmpf();
1175 file_error();
1178 while (!end_of_file) {
1179 ua_ptr1p = fgetuserattr(uaf);
1180 if (ua_ptr1p == NULL) {
1181 if (!feof(uaf)) {
1182 rid_tmpf();
1183 bad_uattr();
1185 else
1186 break;
1189 if (ua_ptr1p->name[0] == '#') {
1191 * If this is a comment, write it back as it
1192 * is.
1194 if (ua_ptr1p->qualifier[0] == '\0' &&
1195 ua_ptr1p->res1[0] == '\0' &&
1196 ua_ptr1p->res2[0] == '\0' &&
1197 (ua_ptr1p->attr == NULL ||
1198 ua_ptr1p->attr->length == 0))
1199 (void) fprintf(fp_uatemp, "%s\n",
1200 ua_ptr1p->name);
1201 else
1203 * This is a commented user_attr entry;
1204 * reformat it, and write it back.
1206 putuserattrent(ua_ptr1p, fp_uatemp);
1207 free_userattr(ua_ptr1p);
1208 continue;
1211 if (!NIS_entry_seen)
1212 info_mask |= WRITE_S_ENTRY;
1213 else
1214 info_mask &= ~WRITE_S_ENTRY;
1217 * See if the new logname already exist in the
1218 * user_attr file
1220 if ((optn_mask & M_MASK) &&
1221 strcmp(lognamp, userattr_st.name) != 0 &&
1222 strcmp(ua_ptr1p->name, userattr_st.name) == 0) {
1223 rid_tmpf();
1224 bad_pasf();
1227 if (strcmp(lognamp, ua_ptr1p->name) == 0) {
1228 info_mask |= FOUND;
1229 if (optn_mask & A_MASK) {
1230 /* password file inconsistent */
1231 rid_tmpf();
1232 bad_pasf();
1235 if (optn_mask & M_MASK) {
1236 int j;
1237 char *value;
1239 for (j = 0; j < UA_KEYS; j++) {
1240 if (ua_opts[j].newvalue != NULL)
1241 continue;
1242 value =
1243 kva_match(ua_ptr1p->attr,
1244 (char *)ua_opts[j].key);
1245 if (value == NULL)
1246 continue;
1247 assign_attr(&userattr_st,
1248 ua_opts[j].key,
1249 value);
1251 free_userattr(ua_ptr1p);
1252 ua_ptr1p = &userattr_st;
1255 if (optn_mask & D_MASK)
1256 info_mask &= ~WRITE_S_ENTRY;
1257 } else if (optn_mask & D_MASK) {
1258 char *rolelist;
1260 rolelist = kva_match(ua_ptr1p->attr,
1261 USERATTR_ROLES_KW);
1262 if (rolelist) {
1263 unassign_role(ua_ptr1p,
1264 rolelist, lognamp);
1268 if (info_mask & WRITE_S_ENTRY) {
1269 putuserattrent(ua_ptr1p, fp_uatemp);
1272 if (!(optn_mask & M_MASK))
1273 free_userattr(ua_ptr1p);
1274 } /* end-of-while-loop */
1276 if (error >= 1) {
1278 msg = BAD_ENT_MESSAGE;
1279 fprintf(stderr, gettext(msg), prognamp);
1283 * Add entry in user_attr if masks is UATTR_MASK
1284 * We don't need to do anything for L_MASK if there's
1285 * no user_attr entry for the user being modified.
1287 if (!(info_mask & FOUND) && !(L_MASK & optn_mask) &&
1288 !(D_MASK & optn_mask)) {
1289 putuserattrent(&userattr_st, fp_uatemp);
1292 /* flush and sync the file before closing it */
1293 if (fflush(fp_uatemp) != 0 || fsync(fd_uatemp) != 0)
1294 file_error();
1295 (void) fclose(fp_uatemp);
1297 /* Done with USERATTR */
1298 (void) fclose(uaf);
1300 } /* End of if info_mask */
1301 /* ignore all signals */
1303 for (i = 1; i < NSIG; i++)
1304 (void) sigset(i, SIG_IGN);
1306 errno = 0; /* For correcting sigset to SIGKILL */
1308 if (unlink(OPASSWD) && access(OPASSWD, 0) == 0)
1309 file_error();
1311 if (link(PASSWD, OPASSWD) == -1)
1312 file_error();
1315 if (rename(PASSTEMP, PASSWD) == -1) {
1316 if (link(OPASSWD, PASSWD))
1317 bad_news();
1318 file_error();
1322 if (info_mask & BOTH_FILES) {
1324 if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) {
1325 if (rec_pwd())
1326 bad_news();
1327 else
1328 file_error();
1331 if (link(SHADOW, OSHADOW) == -1) {
1332 if (rec_pwd())
1333 bad_news();
1334 else
1335 file_error();
1339 if (rename(SHADTEMP, SHADOW) == -1) {
1340 if (rename(OSHADOW, SHADOW) == -1)
1341 bad_news();
1343 if (rec_pwd())
1344 bad_news();
1345 else
1346 file_error();
1350 if (info_mask & UATTR_FILE) {
1351 if (unlink(OUSERATTR_FILENAME) &&
1352 access(OUSERATTR_FILENAME, 0) == 0) {
1353 if (rec_pwd())
1354 bad_news();
1355 else
1356 file_error();
1359 if (link(USERATTR_FILENAME, OUSERATTR_FILENAME) == -1) {
1360 if (rec_pwd())
1361 bad_news();
1362 else
1363 file_error();
1367 if (rename(USERATTR_TEMP, USERATTR_FILENAME) == -1) {
1368 if (rename(OUSERATTR_FILENAME, USERATTR_FILENAME) == -1)
1369 bad_news();
1371 if (rec_pwd())
1372 bad_news();
1373 else
1374 file_error();
1379 ulckpwdf();
1382 * Return 0 status, indicating success
1384 return (0);
1386 } /* end of main */
1388 /* Try to recover the old password file */
1391 rec_pwd(void)
1393 if (unlink(PASSWD) || link(OPASSWD, PASSWD))
1394 return (-1);
1396 return (0);
1399 /* combine two uid_blk's */
1401 void
1402 uid_bcom(struct uid_blk *uid_p)
1404 struct uid_blk *uid_tp;
1406 uid_tp = uid_p->link;
1407 uid_p->high = uid_tp->high;
1408 uid_p->link = uid_tp->link;
1410 free(uid_tp);
1413 /* add a new uid_blk */
1415 void
1416 add_ublk(uid_t num, struct uid_blk *uid_p)
1418 struct uid_blk *uid_tp;
1420 uid_tp = malloc(sizeof (struct uid_blk));
1421 if (uid_tp == NULL) {
1422 rid_tmpf();
1423 file_error();
1426 uid_tp->high = uid_tp->low = num;
1427 uid_tp->link = uid_p->link;
1428 uid_p->link = uid_tp;
1432 * Here we are using a linked list of uid_blk to keep track of all
1433 * the used uids. Each uid_blk represents a range of used uid,
1434 * with low represents the low inclusive end and high represents
1435 * the high inclusive end. In the beginning, we initialize a linked
1436 * list of one uid_blk with low = high = (UID_MIN-1). This was
1437 * done in main().
1438 * Each time we read in another used uid, we add it onto the linked
1439 * list by either making a new uid_blk, decrementing the low of
1440 * an existing uid_blk, incrementing the high of an existing
1441 * uid_blk, or combining two existing uid_blks. After we finished
1442 * building this linked list, the first available uid above or
1443 * equal to UID_MIN is the high of the first uid_blk in the linked
1444 * list + 1.
1446 /* add_uid() adds uid to the link list of used uids */
1447 void
1448 add_uid(uid_t uid)
1450 struct uid_blk *uid_p;
1451 /* Only keep track of the ones above UID_MIN */
1453 if (uid >= UID_MIN) {
1454 uid_p = uid_sp;
1456 while (uid_p != NULL) {
1458 if (uid_p->link != NULL) {
1460 if (uid >= uid_p->link->low)
1461 uid_p = uid_p->link;
1463 else if (uid >= uid_p->low &&
1464 uid <= uid_p->high) {
1465 uid_p = NULL;
1468 else if (uid == (uid_p->high+1)) {
1470 if (++uid_p->high ==
1471 (uid_p->link->low - 1)) {
1472 uid_bcom(uid_p);
1474 uid_p = NULL;
1477 else if (uid == (uid_p->link->low - 1)) {
1478 uid_p->link->low --;
1479 uid_p = NULL;
1482 else if (uid < uid_p->link->low) {
1483 add_ublk(uid, uid_p);
1484 uid_p = NULL;
1486 } /* if uid_p->link */
1488 else {
1490 if (uid == (uid_p->high + 1)) {
1491 uid_p->high++;
1492 uid_p = NULL;
1493 } else if (uid >= uid_p->low &&
1494 uid <= uid_p->high) {
1495 uid_p = NULL;
1496 } else {
1497 add_ublk(uid, uid_p);
1498 uid_p = NULL;
1500 } /* else */
1501 } /* while uid_p */
1503 } /* if uid */
1506 void
1507 bad_perm(void)
1509 (void) fprintf(stderr, gettext("%s: Permission denied\n"), prognamp);
1510 exit(1);
1513 void
1514 bad_usage(char *sp)
1516 if (strlen(sp) != 0)
1517 (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(sp));
1518 (void) fprintf(stderr, gettext("Usage:\n\
1519 %s -a [-c comment] [-h homedir] [-u uid [-o]] [-g gid] \n\
1520 [-s shell] [-f inactive] [-e expire] name\n\
1521 %s -m -c comment | -h homedir | -u uid [-o] | -g gid |\n\
1522 -s shell | -f inactive | -e expire | -l logname name\n\
1523 %s -d name\n"), prognamp, prognamp, prognamp);
1524 if (info_mask & LOCKED)
1525 ulckpwdf();
1526 exit(2);
1529 void
1530 bad_arg(char *s)
1532 (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s));
1534 if (info_mask & LOCKED)
1535 ulckpwdf();
1536 exit(3);
1539 void
1540 bad_name(char *s)
1542 (void) fprintf(stderr, "%s: %s\n", prognamp, gettext(s));
1543 ulckpwdf();
1544 exit(9);
1547 void
1548 bad_uid(void)
1550 (void) fprintf(stderr, gettext("%s: UID in use\n"), prognamp);
1552 ulckpwdf();
1553 exit(4);
1556 void
1557 bad_pasf(void)
1559 msg = "%s: Inconsistent password files\n";
1560 (void) fprintf(stderr, gettext(msg), prognamp);
1562 ulckpwdf();
1563 exit(5);
1566 void
1567 bad_uattr(void)
1569 msg = "%s: Bad user_attr database\n";
1570 (void) fprintf(stderr, gettext(msg), prognamp);
1572 ulckpwdf();
1573 exit(5);
1576 void
1577 file_error(void)
1579 msg = "%s: Unexpected failure. Password files unchanged\n";
1580 (void) fprintf(stderr, gettext(msg), prognamp);
1582 ulckpwdf();
1583 exit(6);
1586 void
1587 bad_news(void)
1589 msg = "%s: Unexpected failure. Password file(s) missing\n";
1590 (void) fprintf(stderr, gettext(msg), prognamp);
1592 ulckpwdf();
1593 exit(7);
1596 void
1597 no_lock(void)
1599 msg = "%s: Password file(s) busy. Try again later\n";
1600 (void) fprintf(stderr, gettext(msg), prognamp);
1602 exit(8);
1605 /* Check for the size of the whole passwd entry */
1606 void
1607 ck_p_sz(struct passwd *pwp)
1609 char ctp[128];
1611 /* Ensure that the combined length of the individual */
1612 /* fields will fit in a passwd entry. The 1 accounts for the */
1613 /* newline and the 6 accounts for the colons (:'s) */
1614 if (((int)strlen(pwp->pw_name) + 1 +
1615 sprintf(ctp, "%d", pwp->pw_uid) +
1616 sprintf(ctp, "%d", pwp->pw_gid) +
1617 (int)strlen(pwp->pw_comment) +
1618 (int)strlen(pwp->pw_dir) +
1619 (int)strlen(pwp->pw_shell) + 6) > (ENTRY_LENGTH-1)) {
1620 rid_tmpf();
1621 bad_arg("New password entry too long");
1625 /* Check for the size of the whole passwd entry */
1626 void
1627 ck_s_sz(struct spwd *ssp)
1629 char ctp[128];
1631 /* Ensure that the combined length of the individual */
1632 /* fields will fit in a shadow entry. The 1 accounts for the */
1633 /* newline and the 7 accounts for the colons (:'s) */
1634 if (((int)strlen(ssp->sp_namp) + 1 +
1635 (int)strlen(ssp->sp_pwdp) +
1636 sprintf(ctp, "%d", ssp->sp_lstchg) +
1637 sprintf(ctp, "%d", ssp->sp_min) +
1638 sprintf(ctp, "%d", ssp->sp_max) +
1639 sprintf(ctp, "%d", ssp->sp_warn) +
1640 sprintf(ctp, "%d", ssp->sp_inact) +
1641 sprintf(ctp, "%d", ssp->sp_expire) + 7) > (ENTRY_LENGTH - 1)) {
1642 rid_tmpf();
1643 bad_arg("New password entry too long");
1647 /* Get rid of the temp files */
1648 void
1649 rid_tmpf(void)
1651 (void) fclose(fp_ptemp);
1653 if (unlink(PASSTEMP)) {
1654 msg = "%s: warning: cannot unlink %s\n";
1655 (void) fprintf(stderr, gettext(msg), prognamp, PASSTEMP);
1658 if (info_mask & BOTH_FILES) {
1659 (void) fclose(fp_stemp);
1661 if (unlink(SHADTEMP)) {
1662 msg = "%s: warning: cannot unlink %s\n";
1663 (void) fprintf(stderr, gettext(msg), prognamp,
1664 SHADTEMP);
1668 if (info_mask & UATTR_FILE) {
1669 (void) fclose(fp_uatemp);
1671 if (unlink(USERATTR_TEMP)) {
1672 msg = "%s: warning: cannot unlink %s\n";
1673 (void) fprintf(stderr, gettext(msg), prognamp,
1674 USERATTR_TEMP);
1679 void
1680 file_copy(FILE *spf, long NIS_pos)
1682 int n;
1683 char buf[1024];
1685 if (fseek(spf, NIS_pos, SEEK_SET) < 0) {
1686 rid_tmpf();
1687 file_error();
1689 while ((n = fread(buf, sizeof (char), 1024, spf)) > 0) {
1690 if (fwrite(buf, sizeof (char), n, fp_stemp) != n) {
1691 rid_tmpf();
1692 file_error();