]> git.pld-linux.org Git - projects/setup.git/blame - joinpasswd.c
- tool for adding new users that appeard in .rpmnew files.
[projects/setup.git] / joinpasswd.c
CommitLineData
31aff165
MM
1/*
2 * $Id$
3 *
4 * Copyright (c) 2001 Michal Moskal <malekith@pld.org.pl>.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Michal Moskal.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY MICHAL MOSKAL AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *
35 *
36 * USAGE: joinpasswd
37 *
38 * Add entries from freshly created {passwd,shadow,group}.rpmnew to existing
39 * {passwd,shadow,group}. It is usable as part of setup package, during upgrade
40 * where new system user/group is to be added. If entry is already found in
41 * system database, it is left, otherwise it is added. UIDs/GIDs are *not* checked
42 * anyhow.
43 *
44 * For typical sizes of files in setup package, it takes about 1 second per
45 * 20000 users in system database on Pentium class machine. After static link
46 * against uClibc it is under 2k on x86. Stdio hasn't been used intentionally.
47 *
48 * Written for PLD GNU/Linux (http://www.pld.org.pl) setup package.
49 *
50 * Compilation against uClibc:
51 * UCROOT=/usr/lib/bootdisk/usr
52 * gcc -I$UCROOT/include -nostdlib -O2 joinpasswd.c $UCROOT/lib/crt0.o \
53 * $UCROOT/lib/libc.a -lgcc -o joinpasswd
54 * strip -R .comment -R .note joinpasswd
55 *
56 * The idea of this program comes from Lukasz Dobrek <dobrek@pld.org.pl>.
57 *
58 */
59
60#include <sys/types.h>
61#include <sys/mman.h>
62#include <sys/stat.h>
63#include <unistd.h>
64#include <fcntl.h>
65#include <stdlib.h>
66#include <string.h>
67
68#define FILE1 "/etc/passwd"
69#define FILE2 "/etc/shadow"
70#define FILE3 "/etc/group"
71
72#define SUFFIX ".rpmnew"
73
74/* #define SILENT */
75
76void eputs(const char *msg)
77{
78 write(2, msg, strlen(msg));
79}
80
81void fatal(const char *msg)
82{
83 eputs(msg);
84 eputs("\n");
85 exit(1);
86}
87
88char *map_file(const char *name, int *sz)
89{
90 int fd;
91 void *ptr;
92 struct stat st;
93
94 fd = open(name, O_RDONLY);
95 if (fd == -1)
96 return NULL;
97 fstat(fd, &st);
98 *sz = st.st_size;
99 ptr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
100 if (ptr == MAP_FAILED)
101 return NULL;
102
103 return ptr;
104}
105
106int exist(char *id, int id_len, char *ptr, int sz)
107{
108 int i;
109
110 for (i = 0; i < sz; ) {
111 if (sz - i > id_len && memcmp(id, ptr + i, id_len + 1) == 0)
112 return 1;
113 while (i < sz && ptr[i] != '\n')
114 i++;
115 i++;
116 }
117
118 return 0;
119}
120
121int join(const char *old_name, const char *new_name)
122{
123 char *old, *new, *id;
124 int i, fd;
125 int old_sz, new_sz;
126
127 new = map_file(new_name, &new_sz);
128 if (new == NULL)
129 return -1;
130
131 old = map_file(old_name, &old_sz);
132 if (old == NULL)
133 fatal("cannot mmap old");
134
135#ifndef SILENT
136 eputs("marging contest of `");
137 eputs(old_name);
138 eputs("' with `");
139 eputs(new_name);
140 eputs("'\n");
141#endif /* SILENT */
142
143 fd = open(old_name, O_WRONLY|O_APPEND);
144
145 for (i = 0; i < new_sz; ) {
146 id = new + i;
147 while (i < new_sz && new[i] != ':' && new[i] != '\n')
148 i++;
149 if (i < new_sz && new[i] == ':') {
150 int id_len, line_len;
151
152 id_len = i - (id - new);
153 while (i < new_sz && new[i] != '\n')
154 i++;
155 if (i < new_sz)
156 i++;
157 line_len = i - (id - new);
158
159 if (!exist(id, id_len, old, old_sz)) {
160#ifndef SILENT
161 eputs(old_name);
162 eputs(": adding `");
163 write(2, id, id_len);
164 eputs("'\n");
165#endif /* SILENT */
166 write(fd, id, line_len);
167 }
168 } else if (i < new_sz)
169 i++;
170 }
171
172#if 0
173 /* user may want to exime this file... */
174 unlink(new_name);
175#endif
176
177 return 0;
178}
179
180int main()
181{
182#if 1
183 join(FILE1, FILE1 SUFFIX);
184 join(FILE2, FILE2 SUFFIX);
185 join(FILE3, FILE3 SUFFIX);
186#else
187 join("test", "test.new");
188#endif
189 return 0;
190}
This page took 0.065437 seconds and 4 git commands to generate.