Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!news.mel.connect.com.au!news.mel.aone.net.au!grumpy.fl.net.au!news.webspan.net!ix.netcom.com!news.enteract.com!feed1.news.erols.com!cpk-news-hub1.bbnplanet.com!news.bbnplanet.com!su-news-hub1.bbnplanet.com!arclight.uoregon.edu!newsfeed.direct.ca!nntp.portal.ca!van-bc!n1van.istar!van.istar!west.istar!ott.istar!istar.net!tor.istar!east.istar!news1.istar.ca!news From: Hume Smith <hclsmith@tallships.istar.ca> Newsgroups: comp.unix.bsd.netbsd.misc Subject: Re: Why no addusr? Date: 10 Jan 1997 21:43:38 GMT Organization: North End TTA Fans and Reed Organ Repairers Lines: 277 Sender: hclsmith@three-elms.isisnet.com Message-ID: <5b6d6a$fut@news.istar.ca> References: <none-ya023480001912962244220001@news.infi.net> <mason-ya023380002012960019340001@news.four.net> <none-ya023480002012962112290001@news.infi.net> <x7zpz8wnxt.fsf@dumbcat.codewright.com> <3a13e94547@emw4maba.slip.gp.fht-esslingen.de> <none-ya023480000201971953550001@news.infi.net> <5aqnum$maq@innocence.interface-business.de> <5b1d03$76@xciv.demon.co.uk> <none-ya023480000801972255110001@news.infi.net> <5b1u1h$spl@keyhole.west.spy.net> <none-ya023480000901971700220001@news.infi.net> Reply-To: Hume Smith <hclsmith@tallships.istar.ca> NNTP-Posting-Host: pt020.tallships.istar.ca In-reply-to: none@domain.com's message of Thu, 09 Jan 1997 17:00:22 -0400 return-receipt-to: Hume Smith <hclsmith@tallships.istar.ca> X-Newsreader: Gnus v5.0.15 Xref: euryale.cc.adfa.oz.au comp.unix.bsd.netbsd.misc:5150 In article <none-ya023480000901971700220001@news.infi.net> none@domain.com (Jeremy Williams) writes: > You see, that main problem that I have is total perl-stupidity. I have no > clue. I'm not a programmer (I'va always ment to learn, but hasn't > everybody). I do scripting on the mac and abject orented programming in > hypercard, but that's useless here. so use tclsh. perl sux anyway; it's for people that loove to show their friends all the wierd symbols they can memorise :) i wrote my mkuser in tcl, i suppose i might as well post it... that's not to say it's robust by any stretch of the imagination; but it's "good enough" for me. and it's a bit longer than 24 lines, but hell, you can write uudecode in three (short) lines in perl; perl is bloated. i probably do a lot of stuff *in* the script that should be foisted off to commands, but... #!/usr/local/bin/tclsh7.6 # Hume Smith <hclsmith@tallships.istar.ca> # 1996 Dec 27 # - converted for NetBSD-Amiga/1.0 # 1996 Sep 1 # create a new user, editing /etc/master.passwd # change time to change password: null or a number of days added to current time # class default class # expire account expire time: null or a number of days added to current time # group default group (name or id) # home default home directory: login name is appended # hphone default home phone # office default office location # shell default shell # skeleton directory copied into new home directories # uidmax greatest default id # uidmin least default id # wphone default work phone array set cfg { uidmin 1000 uidmax 32767 group users class {} change {} expire {} home /local/home/ shell /usr/local/bin/tcsh skeleton /etc/skel office {} hphone {} wphone {}} ;# for three-elms # {uidmin 500 uidmax 32767 group users home /home/ shell /bin/tcsh skeleton /etc/skel} ;# for dess set pwdfile /etc/master.passwd # return boolean stating whether string is all digits proc notalldigits {str} { string length [string trim $str 0123456789] } # return boolean stating whether string is unsafe as a passwd field proc unsafe {str} { regexp \[:\n\] $str } # for testing proc echo args { puts $args } foreach i { {office -office -offic -offi -off -of -o} {wphone -wphone -wphon -wpho -wph -wp -w} {hphone -hphone -hphon -hpho -hpo -hp} {uid -uid -ui -u} {group -group -grou -gro -gr -g} {home -home -hom -ho} {shell -shell -shel -she -sh -s} {expire -expire -expir -expi -exp -ex -e} {change -change -chang -chan -cha -ch} {class -class -clas -cla -cl}} { set x [lindex $i 0] foreach j [lrange $i 1 end] { set opt($j) $x } } # handle commandline arguments if {[llength $argv] < 2} { puts stderr "$argv0: login and real required" exit 10 } set new(login) [lindex $argv 0] set new(real) [lindex $argv 1] array set new [array get cfg] set new(home) $cfg(home)$new(login) unset new(uidmin) new(uidmax) set var {} foreach a [lrange $argv 2 end] { if {"" != "$var"} { set $var $a set var {} } else { if {[catch {set opt($a)} var]} { puts stderr "$argv0: invalid option \"$a\"" } set var new($var) } } if {"" != "$var"} { puts "$argv0: dangling option" exit 22 } if 0 { puts stderr "Usage: $argv0 `login' `real' \[-option value ...\] `login'\tlogin name to be assigned `real'\tuser's real name (or other arbitrary string) options (may be abbreviated): -uid\tUID (defaults to first unused one between $cfg(uidmin) and $cfg(uidmax)) -group\tgroup (defaults to $cfg(group)) -home\thome directory (defaults to $cfg(home)`login') -shell\tlogin shell (defaults to $cfg(shell)) -class\tclass (defaults to \"$cfg(class)\") -change\tdays to password change (defaults to $cfg(change)) -expire\tdays to account expiry (defaults to $cfg(expire)) -office\toffice location -hphone\thome phone -wphone\twork phone" } # validate real name # validate login name if {![regexp ^\[a-z0-9\]+$ $new(login)]} { # this is restrictive but easily done puts stderr "$arg0: login must be digits and lowercase letters" exit 6 } if {[string length $new(login)] > 8} { puts stderr "$arg0: login must not be more than 8 chars" exit 7 } if {![regexp {[a-z]} $new(login)]} { puts stderr "$arg0: login must contain a letter" exit 8 } # read uids and logins from /etc/passwd # fixme: lock it set fid [open $pwdfile r] set ln 0 while {-1 < [gets $fid line]} { incr ln set l [split $line :] if {[llength $l] == 10} { set login [lindex $l 0] if {[info exists uid($login)]} { puts stderr "$argv0: $pwdfile line $l: duplicate login \"$login\"" } { set uid($login) [lindex $l 2] set uidx($uid($login)) {} } } { puts stderr "$argv0: $pwdfile line $l: wrong number of fields" } } close $fid # confirm uniqeness of login if {[info exists uid($new(login))]} { puts stderr "$argv0: login \"$new(login)\" is already in use" exit 2 } # default uid if {![info exists new(uid)]} { for {set i $cfg(uidmin)} {$i <= $cfg(uidmax)} {incr i} { if {![info exists uidx($i)]} { set new(uid) $i break } } } if {![info exists new(uid)]} { puts stderr "$argv0: no available UIDs in range" exit 1 } elseif {[notalldigits $new(uid)]} { puts stderr "$argv0: UID \"$new(uid)\" is not all digits" exit 3 } # default gid if {[notalldigits $new(group)]} { # convert it to numeric form # (i can't find a convenient command for this) if {[catch {exec grep ^$new(group): /etc/group} gl] || ![regexp {^[^:]+:[^:]*:([0-9]+):} $gl {} gid]} { puts stderr "$argv0: no group \"$new(group)\"" exit 12 } set new(group) $gid } # default expire if {[notalldigits $new(expire)]} { puts stderr "$arg0: expire \"$new(expire)\" is not a number" exit 12 } if {[string length $new(expire)]} { set new(expire) [expr 24*60*60*$new(expire)+[clock ]] } # default change if {[notalldigits $new(change)]} { puts stderr "$arg0: change \"$new(expire)\" is not a number" exit 12 } if {[string length $new(change)]} { set new(change) [expr 24*60*60*$new(change)+[clock ]] } # assemble the gecos field foreach i {real office wphone hphone} { if {[regexp , $new($i)]} { puts stderr "$arg0: \"$new($i)\" contains ','" exit 11 } lappend gecos $new($i) unset new($i) } set new(gecos) [join $gecos ,] # check that there are no colons foreach i [array names new] { if {[unsafe $new($i)]} { puts stderr "$arg0: \"$new($i)\" contains ':'" exit 11 } } # # now we attempt to make changes to the system # # create home directory set exec exec ;# for real #set exec echo ;# for testing if {![file exists $new(home)]} { if {[file isdir $cfg(skeleton)]} { $exec cp -R $cfg(skeleton) $new(home) } { $exec mkdir $new(home) } $exec chown -R $new(uid):$new(group) $new(home) } # fixme: it is possible the path already existed but was not a directory set x {} set new(pw) * foreach i {login pw uid group class change expire gecos home shell} { lappend x $new($i) } set tmpfn /etc/chpass.[pid] set fid [open $tmpfn w] exec cat $pwdfile >@ $fid puts $fid [join $x :] close $fid exec pwd_mkdb $tmpfn exit 0 # eof -- Hume Smith <URL:mailto:hclsmith@tallships.istar.ca> <URL:http://dess.tallships.istar.ca/%7Ehclsmith/>