]> git.cameronkatri.com Git - pw-darwin.git/blob - adduser/addgroup.tcl
Free a malloc'ed variable before exiting. Compute line number when parsing
[pw-darwin.git] / adduser / addgroup.tcl
1 #!/usr/bin/tclsh
2 # Copyright (c) 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
3 # All rights reserved.
4 #
5 # addgroup - add a group or add users to a group
6 #
7 # addgroup [-g gid] group [user[,user,...]]
8 #
9 #
10 # addgroup -g 2000 foobar
11 #
12 # Add group `foobar' to group database. Group id is 2000 if
13 # possible or higher. Don't add group `foobar' if `foobar' is
14 # already in group database.
15 #
16 #
17 # addgroup foo blech,bar
18 #
19 # Add user `blech' and user `bar' to group `foo'. Create group
20 # `foo' with default gid if not exists.
21 #
22 #
23 # The option [-g gid] is only for new groups.
24 #
25 # see group(5)
26 #
27 # TODO:
28 # file locking
29 # signal handling
30 # add only users who exist
31 #
32 # $Id$
33
34 # set global variables
35 set etc_group "/etc/group"; #set etc_group "/usr/tmp/group"
36 set gid_start 1000
37 set gid_max 65500
38
39 proc putsErr {string} {
40 if {[catch {open "/dev/stderr" w} stderr]} {
41 puts $stderr
42 } else {
43 puts $stderr $string
44 close $stderr
45 }
46 }
47
48 proc usage {} {
49 putsErr {usage: addgroup group [user]}
50 putsErr { addgroup [-g gid] group [user[,user,...]]}
51 exit 1
52 }
53
54 # check double user names: foo,bla,foo
55 proc double_name {groupmembers} {
56 set l [split $groupmembers ","]
57 if {[llength $l] > 1} {
58 for {set i 0} {$i < [llength $l]} {incr i} {
59 if {[lsearch [lrange $l [expr $i + 1] end] \
60 [lindex $l $i]] != -1} {
61 putsErr "Double user name: [lindex $l $i]"
62 return 1
63 }
64 }
65 }
66 return 0
67 }
68
69 # cleanup and die
70 proc Err {string} {
71 upvar etc_group_new new
72 putsErr "$string"
73 exec rm -f $new
74 exit 1
75 }
76
77 if {$argc < 1} { usage }
78
79 # check options
80 switch -glob -- [lindex $argv 0] {
81 -g* {
82 if {$argc < 2} {
83 putsErr "Missing group id"
84 usage
85 }
86 set g [lindex $argv 1]
87 if {$g < 100 || $g >= $gid_max} {
88 putsErr "Group id out of range 100 < $g < $gid_max"
89 usage
90 }
91 set gid_start $g
92 incr argc -2
93 set argv [lrange $argv 2 end]
94 }
95 -* { usage }
96 }
97
98 if {$argc < 1} { usage }
99
100 # read group name
101 set groupname [lindex $argv 0]
102 if {[string match "*:*" $groupname] != 0} {
103 putsErr "Colon are not allowed in group name: ``$groupname''"
104 usage
105 }
106
107 # read optional group members
108 if {$argc == 2} {
109 set groupmembers [lindex $argv 1]
110 if {[string match "*:*" $groupmembers] != 0} {
111 putsErr "Colon are not allowed in user names: ``$groupmembers''"
112 usage
113 }
114 if {[double_name $groupmembers] != 0} {
115 usage
116 }
117 } else {
118 set groupmembers ""
119 }
120
121
122 # open /etc/group database
123 if {[catch {open $etc_group r} db]} {
124 Err $db
125 }
126
127 # open temporary database
128 set etc_group_new "$etc_group.new";
129 if {[catch {open $etc_group_new w} db_new]} {
130 Err $db_new
131 }
132 set done 0
133
134 while {[gets $db line] >= 0 } {
135 if {$done > 0} {
136 puts $db_new $line
137 continue
138 }
139
140 # ``group:passwd:gid:member''
141 # 0 1 2 3
142 set l [split $line ":"]
143 set group([lindex $l 0]) [lindex $l 2]
144 set gid([lindex $l 2]) [lindex $l 0]
145 set member([lindex $l 0]) [lindex $l 3]
146
147 # found existing group
148 if {[string compare [lindex $l 0] $groupname] == 0} {
149 if {[string compare $groupmembers ""] == 0} {
150 Err "Group exists: ``$groupname''"
151 }
152
153 # add new group members
154 set y [lindex $l 3]
155
156 # group with no group members?
157 if {[string compare $y ""] == 0} {
158 puts $db_new "$line$groupmembers"
159 } else {
160 if {[double_name "$y,$groupmembers"] != 0} {
161 Err "\t$line,$groupmembers"
162 } else {
163 puts $db_new "$line,$groupmembers"
164 }
165 }
166 set done 1
167 } else {
168 puts $db_new $line
169 }
170 }
171
172 # add a new group
173 if {$done == 0} {
174 for {set i $gid_start} {$i < $gid_max} {incr i} {
175 if {[info exists gid($i)] == 0} {
176 puts $db_new "$groupname:*:$i:$groupmembers"
177 set done 1
178 break
179 }
180 }
181
182 # no free group id
183 if {$done == 0} {
184 Err "Cannot find free group id: ``$groupname''"
185 }
186 }
187
188 close $db_new
189 close $db
190 exec cp -pf $etc_group "$etc_group.bak"
191 exec mv -f $etc_group_new $etc_group