summaryrefslogtreecommitdiffstats
path: root/usr.sbin/adduser/addgroup.tcl
blob: e024c8fa1191d7b3ebe57849e33cb1d9ff4819dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/tclsh
# Copyright (c) 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
# All rights reserved.
#
# addgroup - add a group or add users to a group
#
# addgroup [-g gid] group [user[,user,...]]
#
#
# addgroup -g 2000 foobar
#
# Add group `foobar' to group database. Group id is 2000 if 
# possible or higher. Don't add group `foobar' if `foobar' is
# already in group database. 
#
#
# addgroup foo blech,bar
#
# Add user `blech' and user `bar' to group `foo'. Create group
# `foo' with default gid if not exists.
#
#
# The option [-g gid] is only for new groups. 
#
# see group(5)
#
# TODO: 
# 	file locking
#	signal handling
# 	add only users who exist
#
# $FreeBSD$

# set global variables
set etc_group "/etc/group";        #set etc_group "/usr/tmp/group" 
set gid_start 1000
set gid_max 65500

proc putsErr {string} {
    if {[catch {open "/dev/stderr" w} stderr]} {
	puts $stderr
    } else {
	puts $stderr $string
	close $stderr
    }
}

proc usage {} {
    putsErr {usage: addgroup group [user]}
    putsErr {       addgroup [-g gid] group [user[,user,...]]}
    exit 1
}

# check double user names: foo,bla,foo
proc double_name {groupmembers} {
    set l [split $groupmembers ","]
    if {[llength $l] > 1} {
	for {set i 0} {$i < [llength $l]} {incr i} {
	    if {[lsearch [lrange $l [expr $i + 1] end] \
                [lindex $l $i]] != -1} {
		putsErr "Double user name: [lindex $l $i]"
		return 1
	    }
	}
    }
    return 0
}

# cleanup and die
proc Err {string} {
    upvar etc_group_new new
    putsErr "$string"
    exec rm -f $new
    exit 1
}

if {$argc < 1} { usage }

# check options
switch -glob -- [lindex $argv 0]  { 
    -g* {
	if {$argc < 2} { 
	    putsErr "Missing group id"
	    usage 
	}
	set g [lindex $argv 1]
	if {$g < 100 || $g >= $gid_max} {
	    putsErr "Group id out of range 100 < $g < $gid_max"
	    usage
	}
	set gid_start $g
	incr argc -2
	set argv [lrange $argv 2 end]
    }
    -* { usage }
}

if {$argc < 1} { usage }

# read group name
set groupname [lindex $argv 0]
if {[string match "*:*" $groupname] != 0} {
    putsErr "Colon are not allowed in group name: ``$groupname''"
    usage
}

# read optional group members
if {$argc == 2} {
    set groupmembers [lindex $argv 1]
    if {[string match "*:*" $groupmembers] != 0} {
	putsErr "Colon are not allowed in user names: ``$groupmembers''"
	usage
    }
    if {[double_name $groupmembers] != 0} {
	usage
    }
} else {
    set groupmembers ""
}


# open /etc/group database
if {[catch {open $etc_group r} db]} {
    Err $db
}

# open temporary database
set etc_group_new "$etc_group.new"; 
if {[catch {open $etc_group_new w} db_new]} {
    Err $db_new
}
set done 0

while {[gets $db line] >= 0 } {
    if {$done > 0} {
	puts $db_new $line
	continue
    }

    # ``group:passwd:gid:member''
    #     0      1    2    3 
    set l [split $line ":"]
    set group([lindex $l 0]) [lindex $l 2]
    set gid([lindex $l 2]) [lindex $l 0]
    set member([lindex $l 0]) [lindex $l 3]

    # found existing group
    if {[string compare [lindex $l 0] $groupname] == 0} {
	if {[string compare $groupmembers ""] == 0} {
	    Err "Group exists: ``$groupname''"
	}

	# add new group members
	set y [lindex $l 3]

	# group with no group members?
	if {[string compare $y ""] == 0} {
	    puts $db_new "$line$groupmembers"
	} else {
	    if {[double_name "$y,$groupmembers"] != 0} {
		Err "\t$line,$groupmembers"
	    } else {
		puts $db_new "$line,$groupmembers"
	    }
	}
	set done 1
    } else {
	puts $db_new $line
    }
}

# add a new group
if {$done == 0} {
    for {set i $gid_start} {$i < $gid_max} {incr i} {
	if {[info exists gid($i)] == 0} {
	    puts $db_new "$groupname:*:$i:$groupmembers"	    
	    set done 1
	    break
	}
    }

    # no free group id
    if {$done == 0} {
	Err "Cannot find free group id: ``$groupname''"
    }
}

close $db_new
close $db
exec cp -pf $etc_group "$etc_group.bak"
exec mv -f $etc_group_new $etc_group
OpenPOWER on IntegriCloud