#!/bin/sh # @(#) /u/des/src/edq/edq 1.14 08/11/17 17:20:30 # edq: edit disk quotas non-interactively # # INSTALLATION NOTE: # edq must be installed with an additional hard or symbolic link, # using the name in the "SLAVE" variable below, both of which should # be accessible via the same search path; # # Copyright (c) 2001 by Daniel E. Singer. All rights reserved. # Permission is granted to reproduce and distribute this program # with the following conditions: # 1) This copyright notice and the author identification below # must be left intact in the program and in any copies. # 2) Any modifications to the program must be clearly identified # in the source file. # # Written by Daniel E. Singer, Duke Univ. Dept of Computer Science, Jan. 1997 # # Strategy: # - check arguments; # - set some environment variables, including the EDITOR which 'edquota' # will use to edit the temp. quota file; in that case the EDITOR will # actually be the slave mode of this script; # - for each argument group, call 'edquota' with the ACCT name; # - 'edquota' will create a temporary file and call the EDITOR (this script) # with the filename as an argument; # - this script, in SLAVE mode, will rewrite the temp. file with the # new quota info; when SLAVE mode exits, 'edquota' should reread the # temp. file and set the quota; # # since different OS's have different formats for the quota edit file and # other systme differences, see SYS and SYS2 below for supported platforms; # if you add support for additional platforms, please send updates to # # # Note: support for Linux is spotty and only lightly tested, due to variety of # distros and changing quota formats; please see the previous paragraph; # # Modifications: # 4/97, D.Singer # allow for numeric UID instead of account name in argument list; # 11/97, D.Singer # allow for less specific FS parameter, ie, "" for home dir, or # last component of FS mount point; # move stringent arg checking to master; # 1/99, D.Singer # made smarter about finding partitions; # better option processing; # added -r and other remote capabilities; # added env. vars. for block/inode soft/hard ratios; # added -h and detailed help info.; # added -q; # other cleanup; # 12/99, D.Singer # added -n to RSH to fix stdin problem; # 7/2000, D.Singer # various cleanup; # 6/2001, D.Singer # mostly updates for Linux, per patches provided by Dima Nemchenko; # 7/2006, D.Singer # added KMGT factor indicators, per David Zanella suggestion; # 8/2006, D.Singer # added Linux 2.6 support # PROG=`basename "$0"` ORIG_PATH="$PATH" PATH='/usr/sbin:/sbin:/usr/bin:/bin:/usr/ucb' export PATH MASTER="edq" # name of this script in MASTER mode SLAVE="edq-slave" # name of this script in SLAVE mode EDIT_QUOTA_PROG="edquota" # program that actually changes system quotas #EDIT_QUOTA_PROG="./edq-x" # for testing # # environment variables, and their defaults: # DEFAULT_ISR="0.20" # default inodes soft ratio DEFAULT_IHR="1.25" # default inodes hard ratio DEFAULT_BHR="1.25" # default blocks hard ratio : ${INODES_SOFT_RATIO:="$DEFAULT_ISR"} # ratio of inodes to number of blocks, if # inodes not specified : ${INODES_HARD_RATIO:="$DEFAULT_IHR"} # ratio of inodes hard-limit to soft-limit : ${BLOCKS_HARD_RATIO:="$DEFAULT_BHR"} # ratio of blocks hard-limit to soft-limit SYS=`uname -sr` SYS2= # shortened AWK="awk" RSH="rsh -n" SH="/bin/sh" GET_HOST="uname -n" case "$SYS" in "Linux 2.2"*) DF="/bin/df" SYS2='Linux 2.2' ;; "Linux 2.4"*) DF="/bin/df" SYS2='Linux 2.4' ;; "Linux 2.6"*) DF="/bin/df" SYS2='Linux 2.6' ;; "OSF1 "*) DF="/usr/bin/df -k" SYS2='OSF1' ;; "SunOS 4"*) AWK="nawk" DF="/usr/bin/df" SYS2='SunOS 4' ;; "SunOS 5"*) AWK="nawk" DF="/usr/sbin/df -k" SYS2='SunOS 5' ;; *) echo "$PROG: do not know how to edit quotas on \"$SYS\"." >&2 exit 1 esac # # function to determine the path to PROG so that spawned programs wont # say "command not found". # Usage: get_path [path/]file # use 'ORIG_PATH="$PATH"' at the beginning of the program. # get_path() { case "$1" in '/'*) PROG_PATH=`dirname "$1"` ;; *'/'*) PROG_PATH=`dirname "$1"` #cd "$PROG_PATH" #PROG_PATH="`pwd`" PROG_PATH="`cd \"$PROG_PATH\"; pwd`" ;; *) set -f _IFS="$IFS" IFS=':' set -- X $ORIG_PATH shift IFS="$_IFS" set +f for PC do if [ -f "$PC/$PROG" -a -x "$PC/$PROG" ]; then PROG_PATH="$PC" break fi done esac # case where no path is given, and "." is in the PATH [ -z "$PROG_PATH" ] && PROG_PATH=`pwd` } # # function to check partition info: # if remote syntax, try remote; # if blank, try to get from passwd db; # if partial path, try to resolve; # if local partition, get real mount point; # if remote partition, try remote; # check_partition() { # # see if it's a remote partition syntax; # case "$PART" in *?:*) # # break the PART up into RHOST and PART # set -f _IFS="$IFS" IFS=":" set -- X $PART shift IFS="$_IFS" set +f RHOST="$1" PART="$2" REMOTE=1 IS_REMOTE=1 return 0 esac if [ -z "$PART" ]; then # # if PART is empty, use the home dir from the passwd entry # PART=`{ # # list out the local passwd file, and look for matches # in the NIS db; # cat /etc/passwd #ypcat passwd 2>&- ypmatch "$ACCT" passwd.byname 2>&- ypmatch "$ACCT" passwd.byuid 2>&- } | $AWK -F: 'BEGIN { ACCT = "'"$ACCT"'"; # alphanumeric or numeric ACOL = (ACCT ~ /^[0-9]+$/) ? 3 : 1; FOUND = 0; PART = ""; } { if (ACCT == $ACOL) { PART = $6; FOUND = 1; # keep from getting a "broken pipe" message while (getline) ; exit; } } END { print PART; exit (!FOUND); }'` || { ERROR_MSG="no account found for \"$ACCT\"" ERROR=1 return 1 } if [ -z "$PART" ]; then ERROR_MSG="no home dir for \"$ACCT\"" ERROR=1 return 1 fi fi #echo "PART=\"$PART\"" #exit # # identify the local or remote partition; # remember that this could be a loopback mount, and the # initial mount point is needed; # # # look in the output of DF; # DF output looks something like this: #Filesystem kbytes used avail capacity Mounted on #/dev/dsk/c1t0d0s0 96167 24620 71451 26% / #/proc 0 0 0 0% /proc #fd 0 0 0 0% /dev/fd #swap 720924 196 720728 1% /tmp #mentor:/export/mentor4 # 4891408 3152200 1250064 72% /home/mentor4 # DF_OUT=`case "$PART" in /*) # # try to wake it up if its an automount # ls -ld "$PART/." >&- 2>&- $DF "$PART" 2>&- ;; *) $DF 2>&- esac | # # clean up the DF output a little # $AWK '{ if ($1 == "Filesystem") next; if (HOLD == 1) { print LAST " " $0; HOLD = 0; next; } if (NF == 1) { HOLD = 1; LAST = $1; next; } print; }'` # # try to refine our conception of PATH # HOLD_PART="$PART" PART=`echo "$DF_OUT" | $AWK 'BEGIN { SYS2 = "'"$SYS2"'"; PART = "'"$PART"'"; ANCHORED = (PART ~ /^\//); NPART = ""; REMOTE = "'"$REMOTE"'"; IS_REMOTE = 0; } { # # if an anchored path, there should be just one data # line from DF; # this should be the correct partition info; # if (ANCHORED == 1) { #print "ANCHORED" >"/dev/tty"; if ($1 ~ /^\/dev\//) #NPART = (SYS2 == "Linux 2.2" || SYS2 == "Linux 2.4" || SYS2 == "Linux 2.6") ? $1 : $6; NPART = (SYS2 ~ /^Linux 2\.[246]$/) ? $1 : $6; else if ($1 ~ /^\/[A-Za-z]/) NPART = $1; else if (REMOTE == 1 && $1 ~ /^[A-Za-z][_A-Za-z0-9]*:\//) NPART = $1; exit; } # # otherwise ... # PAT = "/" PART "$"; # eg, "/home2$" # # local direct mount? # if ($1 ~ /^\/dev\//) { if ($6 ~ PAT) { NPART = $6; exit; } } # # local loopback mount? # else if ($1 ~ /^\/[A-Za-z]/) { if ($6 ~ PAT) { NPART = $1; exit; } } # # a remote mount? # else if (REMOTE == 1) { if ($1 ~ /^[a-z][a-z0-9]*:\// && $6 ~ PAT) { NPART = $1; exit; } } } END { print NPART; exit (NPART == ""); }'` || { if [ "$REMOTE" = 0 ]; then ERROR_MSG="cannot find a local mounted partition for \"$HOLD_PART\"" else ERROR_MSG="cannot find a mounted partition for \"$HOLD_PART\"" fi ERROR=1 return 1 } # # see if it's a remote partition syntax: # something in front of a colon; # case "$PART" in ?*:*) # # break the PART up into RHOST and PART # set -f _IFS="$IFS" IFS=":" set -- X $PART shift IFS="$_IFS" set +f RHOST="$1" PART="$2" IS_REMOTE=1 esac #echo "RHOST=\"$RHOST\"" #echo "PART=\"$PART\"" #exit return 0 } # # fix a quota figure; # fractions are OK, but convert to non-fraction # usage: fix_num var [dflt_mag] # fix_num() { _var="$1" _dflt_mag="$2" eval "_num=\"\$$1\"" _num=`$AWK <&- -v "num=$_num" -v "dflt_mag=$_dflt_mag" 'BEGIN { # first convert any letters to upper case; num = toupper(num); if (num ~ /[KMGT]$/) { mag = substr(num,length(num)); num = substr(num,1,length(num)-1); } else mag = toupper(dflt_mag); if (num !~ /^[0-9]+$/ && num !~ /^[0-9]*\.[0-9]+$/) exit 1; if (mag == "T") { if (dflt_mag == "T") mag = ""; else { num *= 1024; mag = "G"; } } if (mag == "G") { if (dflt_mag == "G") mag = ""; else { num *= 1024; mag = "M"; } } if (mag == "M") { if (dflt_mag == "M") mag = ""; else { num *= 1024; mag = "K"; } } if (mag == "K") { if (dflt_mag == "K") mag = ""; else { num *= 1024; mag = ""; } } if (num ~ /\./) num = int(num + .5); print num; exit 0; }'` if [ $? != 0 ]; then echo "$prog: invalid $_var specification!" >&2 return 1 fi eval "$_var=\"\$_num\"" return 0 } # # MASTER or SLAVE mode # case "$PROG" in # # MASTER mode: calls EDIT_QUOTA_PROG which calls SLAVE mode # via the EDITOR or VISUAL environment variable; # "$MASTER") #echo "@=\"$*\"" USAGE="Usage: $PROG [-hqr] acct,[partn],blocks[,inodes] ..." HELP=" $USAGE -h help, print this message and exit; -q quiet, do not print normal status messages; -r remote, if the partition is not found locally, look for a remote mount; acct account name whose quota to change (can be numeric UID); partn partition with the quota to change; if empty, the home partition of the acct will be used; if a partial path, an attempt will be made to locate the correct partition; if a \`host:path' construct is used, a remote mount is assumed; blocks number of 1KB blocks for the blocks soft-limit; inodes number of inodes for the inodes soft-limit; if not specified, a set ratio to blocks is used; blocks and inodes can be optionally followed by K, M, G, or T to indicate kilobytes, megabytes, gigabytes, or terabytes; also, fractions can be specified, eg, \"1.5G\"; Environment variables: INODES_SOFT_RATIO default ratio of inodes to number of blocks (default = $DEFAULT_ISR); BLOCKS_HARD_RATIO ratio of blocks hard-limit to soft-limit (default = $DEFAULT_BHR); INODES_HARD_RATIO ratio of inodes hard-limit to soft-limit (default = $DEFAULT_IHR); " QUIET=0 # quiet, fewer messages QUIET_PASS= # flag to pass REMOTE=0 IS_REMOTE=0 RHOST= syntax_error() { echo "$$PROG: option syntax error." >&2 echo "$USAGE" >&2 exit 1 } arg_syntax_check() { [ "$1" -lt 1 ] && syntax_error } # # process command line options # while [ $# -ne 0 ]; do OPT="$1" case "$OPT" in -h) echo "$HELP" exit 0 ;; -q) QUIET=1 QUIET_PASS=" -q" ;; -r) REMOTE=1 ;; # # options with argument # -c) # shift # arg_syntax_check "$#" # CARG="$1" # CFLAG=1 # ;; # ... --) shift break ;; # unknown option -?) syntax_error ;; # compound option -??*) # break up a compound option NEW_OPTS=`$AWK 'BEGIN { OPT_STR = "'"$OPT"'"; LEN = length(OPT_STR); NEW_OPTS = ""; STATUS = 0; for (POS=2; POS+0 <= LEN; ++POS) { OPT = substr(OPT_STR,POS,1); if (OPT !~ /[a-zA-Z0-9_]/) STATUS = 1; NEW_OPTS = NEW_OPTS " -" OPT; } print NEW_OPTS; exit STATUS; }' <&-` || { syntax_error } shift set -- $NEW_OPTS ${1:+"$@"} continue ;; # end of options, just command arguments left *) break esac shift done # # need at least one argument group # [ $# -eq 0 ] && syntax_error #GROUPS="$@" # # set env. vars. for 'edquota' # VISUAL="$SLAVE" EDITOR="$SLAVE" export VISUAL EDITOR get_path "$0" PATH="$PROG_PATH:$PATH" export PATH # need this for bash "$*" handling below SEP=' ' [ "${BASH_VERSION:+1}" ] && SEP=',' #for GROUP in $GROUPS; do for GROUP do set -f # if 2nd arg (PART) is empty, change it to a "-", # otherwise it will not register as a blank parameter; GROUP=`$AWK <&- 'BEGIN { GROUP = "'"$GROUP"'"; N = split(GROUP,A,/[,;]/); if (A[2] == "") A[2] = "-"; STR = A[1]; for (I=2; I+0 <= N; ++I) STR = STR "," A[I]; print STR; }'` _IFS="$IFS" IFS=',;' set -- $GROUP # # check that the group looks reasonable # $AWK <&- 'BEGIN { N = split("'"$*"'",ARGS,"'"$SEP"'"); if (N != 3 && N != 4) exit 1; ACCT = ARGS[1]; PART = ARGS[2]; BLOCKS = toupper(ARGS[3]); INODES = toupper(ARGS[4]); if (ACCT !~ /^[a-z][a-z0-9]*$/ && ACCT !~ /^[0-9]+$/) exit 1; # we"re less strict on this now #if (PART !~ /^\/[a-z][a-z0-9]*/) # exit 1; if (BLOCKS !~ /^([0-9]+|([0-9]*.[0-9]+))[KMGT]?$/) exit 1; if (INODES != "" && INODES !~ /^([0-9]+|([0-9]*.[0-9]+))[KMGT]?$/) exit 1; exit 0; }' || { echo "$PROG: malformed argument \"$GROUP\"." >&2 continue } IFS="$_IFS" set +f ACCT="$1" PART="$2" [ "/$PART" = '/-' ] && PART= case "$PART" in ~*) PART=`csh -cf "echo $PART"` esac BLOCKS="$3" INODES="$4" # # resolve the partition # check_partition || { echo "$PROG: ${ERROR_MSG}." >&2 exit $ERROR } # # turn blocks into a number representing KBs # fix_num BLOCKS K # # if INODES is blank, then go to the default ratio; # if INODES is explicitely zero, then leave it as such; # if [ -z "$INODES" ]; then INODES=`$AWK -v "B=$BLOCKS" -v "R=$INODES_SOFT_RATIO" 'BEGIN { print int(B * R); }'` else fix_num INODES fi #echo "BLOCKS = $BLOCKS" #echo "INODES = $INODES" #exit # # if IS_REMOTE, let the remote host handle it from here; # if [ "$IS_REMOTE" = 1 ]; then if [ "$RHOST" != `$GET_HOST` ]; then # be careful to preserve the env. vars.; # there must be a better way to do this... E="INODES_HARD_RATIO=\"$INODES_HARD_RATIO\" BLOCKS_HARD_RATIO=\"$BLOCKS_HARD_RATIO\"; export INODES_HARD_RATIO BLOCKS_HARD_RATIO;" $RSH "$RHOST" "$SH -c '$E $PROG_PATH/$PROG$QUIET_PASS \"$ACCT,$PART,$BLOCKS,$INODES\"'" else # PART may need a little more refining... $PROG_PATH/$PROG$QUIET_PASS "$ACCT,$PART,$BLOCKS,$INODES" fi else #TINODES= #[ "$INODES" -ne '0' ] && TINODES=":$INODES" [ "$QUIET" -eq 0 ] && #echo "$PROG: calling $EDIT_QUOTA_PROG for \"$ACCT\" with \"$BLOCKS$TINODES\" on \"$PART\"." >&2 echo "$PROG: calling $EDIT_QUOTA_PROG for \"$ACCT\" with \"$BLOCKS:$INODES\" on \"$PART\"." >&2 #echo "$ACCT $PART $BLOCKS $INODES" #exit # # set env. vars. that will be used by SLAVE # export ACCT PART BLOCKS INODES QUIET # # call "edquota acct" # $EDIT_QUOTA_PROG "$ACCT" fi done exit ;; # # SLAVE mode, called by EDIT_QUOTA_PROG; this is the "$EDITOR"; # info is passed in via env. vars., thus the lack of options; # "$SLAVE") USAGE="Usage: $PROG file" # # check command line options # while [ $# -ne 0 ]; do case "$1" in -*) echo "$PROG: option syntax error." >&2 echo "$USAGE" >&2 exit 1 ;; *) break esac shift done # # need exactly one argument: the temp. file name # [ $# -ne 1 ] && { echo "$PROG: option syntax error." >&2 echo "$USAGE" >&2 exit 1 } FILE="$1" [ ! -r "$FILE" ] && { echo "$PROG: cannot read \"$FILE\"." >&2 exit 1 } [ ! -w "$FILE" ] && { echo "$PROG: cannot write \"$FILE\"." >&2 exit 1 } # # do a quickie check of the environment variables that # should have been set in MASTER mode; # [ -z "$ACCT" ] && { echo "$PROG: no ACCT environment variable." >&2 exit 1 } case "$PART" in /*) ;; *) echo "$PROG: invalid PART environment variable." >&2 exit 1 esac case "$BLOCKS" in [0-9]*) ;; *) echo "$PROG: invalid BLOCKS environment variable." >&2 exit 1 esac case "$INODES" in [0-9]*) ;; *) echo "$PROG: invalid INODES environment variable." >&2 exit 1 esac #[ "/$PART" = '/' -o ! -d "$PART" ] && { # echo "$PROG: cannot find partition \"$PART\"." >&2 # exit 1 #} # and fall thru to continue processing below (saves some indentation) ;; *) echo "$PROG: called by unknown name." >&2 exit 1 esac # # continue SLAVE processing # LINES=`$AWK < "$FILE" 'BEGIN { SYS2 = "'"$SYS2"'"; # OS ACCT = "'"$ACCT"'"; # account name PART = "'"$PART"'"; # partition full path BLOCKS = "'"$BLOCKS"'"; # quota blocks INODES = "'"$INODES"'"; # quota inodes #INODES_SOFT_RATIO = '"$INODES_SOFT_RATIO"'; INODES_HARD_RATIO = '"$INODES_HARD_RATIO"'; BLOCKS_HARD_RATIO = '"$BLOCKS_HARD_RATIO"'; OSF_PART_PAT = "^" PART ":"; # also Linux 2.2 LX_2_4_PART_PAT = "^Device " PART " "; LX_2_6_PART_PAT = "^ *" PART " "; SUN_PART_PAT = "^fs " PART " "; #if (INODES == 0) # INODES = int(BLOCKS * INODES_SOFT_RATIO); BLOCKS_SOFT = BLOCKS; BLOCKS_HARD = int(BLOCKS * BLOCKS_HARD_RATIO); INODES_SOFT = INODES; INODES_HARD = int(INODES * INODES_HARD_RATIO); } { # just slurp up all the lines right now LINES[++CNT] = $0; } # substitute a particular number in a line with a new number function subnum(LINE,WHICH,NUMBER) { SUB_LINE = LINE; # LINE that will get chopped up; DUP_LINE = ""; # LINE will rebuild here; for (TRY=1; TRY+0 <= WHICH; ++TRY) { # # looking for a non-alphanumeric followed by a digit; # this will not work for a number at the beginning of a line, # but that should not matter here; # POS = match(SUB_LINE,/[^A-Za-z0-9][0-9]+/); if (POS == 0) break; if (TRY == WHICH) { # this is the one we are looking for; # combine the appropriate parts from DUP_LINE and # SUB_LINE, and stick the new NUMBER in the middle; DUP_LINE = DUP_LINE substr(SUB_LINE,1,POS) NUMBER substr(SUB_LINE,POS+RLENGTH); return DUP_LINE; } # add the matched part to DUP_LINE, # and remove it from SUB_LINE; DUP_LINE = DUP_LINE substr(SUB_LINE,1,POS+RLENGTH-1); SUB_LINE = substr(SUB_LINE,POS+RLENGTH); } # number not found, just return the original line; return LINE; } #---------------------------------------------------- # DEC/OSF1 edquota format: #Quotas for user des: #/cs/lynx/home1: blocks in use: 9, limits (soft = 0, hard = 0) # inodes in use: 7, limits (soft = 0, hard = 0) #/cs/lynx/home2: blocks in use: 0, limits (soft = 0, hard = 0) # inodes in use: 0, limits (soft = 0, hard = 0) #---------------------------------------------------- # Linux 2.2 edquota format: #Quotas for user des: #/dev/sda6: blocks in use: 244, limits (soft = 0, hard = 0) # inodes in use: 58, limits (soft = 0, hard = 0) #---------------------------------------------------- # Linux 2.4 edquota format: #Edit block and inode quota for user des: #Device /dev/sda1 (/): #Used 76KB, limits: soft=50000 hard=60000 #Used 19 inodes, limits: soft=0 hard=0 #---------------------------------------------------- # Linux 2.6 edquota format: #Disk quotas for user xzhang (uid 65021): #Filesystem blocks soft hard inodes soft hard # /dev/mapper/Volume0 52 10485760 10485760 7 0 0 #---------------------------------------------------- # SunOS & Solaris edquota format: #fs /home/falstaff1 blocks (soft = 0, hard = 0) inodes (soft = 0, hard = 0) #fs /home/falstaff2 blocks (soft = 0, hard = 0) inodes (soft = 0, hard = 0) #---------------------------------------------------- END { if (SYS2 == "OSF1" || SYS2 == "Linux 2.2") { if (LINES[1] != "Quotas for user " ACCT ":") { exit 1; } MATCH = 0; for (I=2; I+0 <= CNT; ++I) { if (MATCH == 1) { if (LINES[I] ~ /^[ ]+inodes /) { LINES[I] = subnum(LINES[I],2,INODES_SOFT); LINES[I] = subnum(LINES[I],3,INODES_HARD); } MATCH = 0; break; } if (LINES[I] ~ OSF_PART_PAT) { MATCH = 1; LINES[I] = subnum(LINES[I],2,BLOCKS_SOFT); LINES[I] = subnum(LINES[I],3,BLOCKS_HARD); } } } else if (SYS2 == "Linux 2.4") { if (LINES[1] != "Edit block and inode quota for user " ACCT ":") { exit 1; } MATCH = 0; for (I=2; I+0 <= CNT; ++I) { if (MATCH == 1) { LINES[I] = subnum(LINES[I],2,BLOCKS_SOFT); LINES[I] = subnum(LINES[I],3,BLOCKS_HARD); ++MATCH; continue; } if (MATCH == 2) { LINES[I] = subnum(LINES[I],2,INODES_SOFT); LINES[I] = subnum(LINES[I],3,INODES_HARD); MATCH = 0; break; } if (LINES[I] ~ LX_2_4_PART_PAT) MATCH = 1; } } else if (SYS2 == "Linux 2.6") { if (LINES[1] !~ ("^Disk quotas for user " ACCT)) { exit 1; } if (LINES[2] !~ /^ *Filesystem /) { exit 1; } for (I=3; I+0 <= CNT; ++I) { if (LINES[I] ~ LX_2_6_PART_PAT) { LINES[I] = subnum(LINES[I],2,BLOCKS_SOFT); LINES[I] = subnum(LINES[I],3,BLOCKS_HARD); LINES[I] = subnum(LINES[I],5,INODES_SOFT); LINES[I] = subnum(LINES[I],6,INODES_HARD); break; } } print LX_2_6_PART_PAT >"/dev/tty"; for (I=1; I+0 <= CNT; ++I) { print LINES[I] > "/dev/tty"; } } else if (SYS2 == "SunOS 4" || SYS2 == "SunOS 5") { for (I=1; I+0 <= CNT; ++I) { if (LINES[I] ~ SUN_PART_PAT) { LINES[I] = subnum(LINES[I],1,BLOCKS_SOFT); LINES[I] = subnum(LINES[I],2,BLOCKS_HARD); LINES[I] = subnum(LINES[I],3,INODES_SOFT); LINES[I] = subnum(LINES[I],4,INODES_HARD); break; } } } for (I=1; I+0 <= CNT; ++I) { print LINES[I]; } exit 0; }'` # # finish up SLAVE mode: # now, if everything went OK, just write the modified lines out to the file # and exit; edquota should pick it back up from there; # STAT="$?" if [ "$STAT" -ne 0 ]; then echo "$PROG: NOT changing quota for \"$ACCT\" on \"$PART\"!" >&2 exit $STAT fi #[ "$INODES" -eq 0 ] && INODES=`expr "$BLOCKS" / 5` [ "$QUIET" -eq 0 ] && echo "$PROG: changing quota for \"$ACCT\" to \"$BLOCKS:$INODES\" on \"$PART\"." >&2 echo "$LINES" > "$FILE" exit