root/usr/src/cmd/oamuser/user/proj.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#include <project.h>
#include <unistd.h>
#include <userdefs.h>
#include <errno.h>
#include <nss_dbdefs.h>
#include "users.h"
#include "messages.h"

int
edit_project(char *login, char *new_login, projid_t projids[], int overwrite)
{
        char **memptr;
        char t_name[] = "/etc/projtmp.XXXXXX";
        FILE *e_fptr, *t_fptr;
        struct project *p_ptr;
        struct project p_work;
        char workbuf[NSS_LINELEN_PROJECT];
        int i, modified = 0;
        struct stat sbuf;
        int p_length;
        char p_string[NSS_LINELEN_PROJECT];
        long p_curr = 0;
        int exist;
        int fd;

        if ((e_fptr = fopen(PROJF_PATH, "r")) == NULL) {
                return (EX_UPDATE);
        }

        if (fstat(fileno(e_fptr), &sbuf) != 0)
                return (EX_UPDATE);

        if ((fd = mkstemp(t_name)) < 0) {
                return (EX_UPDATE);
        }

        if ((t_fptr = fdopen(fd, "w+")) == NULL) {
                (void) close(fd);
                (void) unlink(t_name);
                return (EX_UPDATE);
        }

        /*
         * Get ownership and permissions correct
         */

        if (fchmod(fd, sbuf.st_mode) != 0 ||
            fchown(fd, sbuf.st_uid, sbuf.st_gid) != 0) {
                (void) fclose(t_fptr);
                (void) unlink(t_name);
                return (EX_UPDATE);
        }

        p_curr = ftell(e_fptr);

        /* Make TMP file look like we want project file to look */

        while (fgets(p_string, NSS_LINELEN_PROJECT - 1, e_fptr)) {
                /* While there is another group string */

                p_length = strlen(p_string);
                (void) fseek(e_fptr, p_curr, SEEK_SET);
                p_ptr = fgetprojent(e_fptr, &p_work, &workbuf,
                    sizeof (workbuf));
                p_curr = ftell(e_fptr);

                if (p_ptr == NULL) {
                        /*
                         * tried to parse a proj string over
                         * NSS_LINELEN_PROJECT chars
                         */
                        errmsg(M_PROJ_ENTRY_OVF, NSS_LINELEN_PROJECT);
                        modified = 0; /* bad project file: cannot rebuild */
                        break;
                }

                /* first delete the login from the project, if it's there */
                if (overwrite || !projids) {
                        if (p_ptr->pj_users != NULL) {
                                for (memptr = p_ptr->pj_users; *memptr;
                                    memptr++) {
                                        if (strcmp(*memptr, login) == 0) {
                                                /* Delete this one */
                                                char **from = memptr + 1;
                                                p_length -= (strlen(*memptr)+1);
                                                do {
                                                        *(from - 1) = *from;
                                                } while (*from++);

                                                modified++;
                                                break;
                                        }
                                }
                        }
                }

                /* now check to see if project is one to add to */
                if (projids) {
                        for (i = 0; projids[i] != -1; i++) {
                                if (p_ptr->pj_projid == projids[i]) {
                                        /* Scan for dups */
                                        exist = 0;
                                        for (memptr = p_ptr->pj_users; *memptr;
                                            memptr++) {
                                                if (strncmp(*memptr, new_login ?
                                                    new_login : login,
                                                    strlen(*memptr)) == 0)
                                                        exist++;
                                        }
                                        p_length += strlen(new_login ?
                                            new_login : login) + 1;

                                        if (p_length >=
                                            NSS_LINELEN_PROJECT - 1) {
                                                errmsg(M_PROJ_ENTRY_OVF,
                                                    NSS_LINELEN_PROJECT);
                                                break;
                                        } else {
                                                if (!exist) {
                                                *memptr++ = new_login ?
                                                    new_login : login;
                                                *memptr = NULL;
                                                modified++;
                                                }
                                        }
                                }
                        }
                }
                putprojent(p_ptr, t_fptr);
        }

        (void) fclose(e_fptr);
        (void) fclose(t_fptr);

        /* Now, update project file, if it was modified */
        if (modified && rename(t_name, PROJF_PATH) < 0) {
                (void) unlink(t_name);
                return (EX_UPDATE);
        }

        (void) unlink(t_name);
        return (EX_SUCCESS);
}