1

I am looking for a way to programmatically maintain a consistent umask in the files /etc/profile and /etc/bashrc. They have an entry such as follows:

if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
  umask 002
else
  umask 022
fi

So I would like to programmatically check for the first if statement above. If found, check to verify the next line is a umask (and not a comment) and if so, set it back to my standard umask if it has deviated from it. I realize I could just copy the entire file but would rather not disturb other changes that may have been made. I'm sure someone has done with with sed/awk/grep and can share or perhaps have thoughts on how to achieve this? I am required to maintain a umask for the login shell and for the non-login shell. It references this at https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/assembly_managing-the-umask_configuring-basic-system-settings. Thank you.

8
  • 3
    Have you considered putting your customizations in /etc/profile.d so that they are not overwritten by changes to /etc/profile?
    – doneal24
    Commented Jan 26, 2022 at 20:12
  • Yes, please edit your question and explain why you want this. The normal way for this sort of thing is to edit your own personal ~/.bashrc and/or ~/.profile files or, if you want it to be applied to new users as well, to change the files in /etc/skel. If you explain what your final objective is, we should be able to give a better solution (messing with the standard files in /etc is very rarely the right approach).
    – terdon
    Commented Jan 26, 2022 at 20:25
  • To address your request, I just added the following to my question "I am required to maintain a umask for the login shell and for the non-login shell. It references this at access.redhat.com/documentation/en-us/red_hat_enterprise_linux/…." So its something I am required to do. Hope this helps.
    – Kyle
    Commented Jan 26, 2022 at 20:44
  • For what user? All users? All non-system users? Your user? New users? I am guessing it will be for all non-system users based on the code you show, but it would help to be sure. The details will depend on that. In any case, the solution will be to either use files inside /etc/profile.d or user-specific ones in the relevant user's $HOME directories.
    – terdon
    Commented Jan 26, 2022 at 21:35
  • 2
    You want to parse the startup scripts to check if they have changed your umask from its default and it change it to the default only if it has been changed? Why not just set the umask?
    – symcbean
    Commented Jan 26, 2022 at 23:29

2 Answers 2

0

I fail to understand why this could make any sense (see comments), but your task can be done like this:

sed -i".bak" '\_if \[ $UID -gt 199 ] && \[ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then_,/^[^#]*else/s/^\([^#]*umask\).*/\1 002/' /etc/profile /etc/bashrc

The address range covers all lines between your if clause and the next not-comment else. In this line a not-comment umask is changed to 002.

Note that you need to escape the [ and that I did choose the underscore as delimiter for the first address to avoid escaping all slashes.

If really somebody/something is changing those files, you might consider using a more flexible pattern for the if line; otherwise changing the if line along with the umask line will break the script. Maybe

sed -i".bak" '/if.*$UID *-gt *199/,/^[^#]*else/s/^\([^#]*umask\).*/\1 002/' /etc/profile /etc/bashrc
4
  • Thank you so much! This is VERY close but unfortunately, it duplicates the umask entry as in the following example: umask 002 002 I hope I'll be able to figure it out but as always, assistance/ideas welcome!
    – Kyle
    Commented Jan 27, 2022 at 15:06
  • Stupid me! I corrected it.
    – Philippos
    Commented Jan 27, 2022 at 16:35
  • Why is there an escaped undesrcore in sed -i".bak" '\_if ...? Typo?
    – terdon
    Commented Jan 28, 2022 at 9:51
  • 1
    @terdon As written, to use the underscore as delimiter for the address pattern. From the man: In a context address, the construction "\cBREc", where c is any character other than <backslash> or <newline>, shall be identical to "/BRE/". If the character designated by c appears following a <backslash>, then it shall be considered to be that literal character, which shall not terminate the BRE. For example, in the context address "\xabc\xdefx", the second x stands for itself, so that the BRE is "abcxdef".
    – Philippos
    Commented Jan 28, 2022 at 10:38
0

I am looking for a way to programmatically maintain a consistent umask in the files /etc/profile and /etc/bashrc. They have an entry such as follows:

if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
  umask 002
else
  umask 022
fi

I would like to programmatically check for the first if statement above. If found, check to verify the next line is a umask (and not a comment) and if so, set it back to my standard umask if it has deviated from it.

Why would comments appear in the middle of the if command? There are none in your example. You can simplify this process greatly by having the code identically formatted anywhere you need to check for its presence. If you can do that, here's a Python script that will do what you're asking. Make sure the code text between the triple quotes is exactly the same at is appears in the files you want to check (although in this case it really doesn't cause any problems if the code appears more than once in a script):

snippet = '''
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
  umask 002
else
  umask 022
fi
'''
with open('/etc/profile','r+') as f:
    if snippet not in f.read():
        f.write(snippet)
with open('/etc/bashrc','r+') as f:
    if snippet not in f.read():
        f.write(snippet)

Because the write locations are root-owned you would need to use sudo when invoking the script: sudo python myscript.py or sudo python3 myscript.py. The script checks if /etc/bashrc and /etc/profile contain the block of text defined in snippet and if not it is appended to the file(s).

Is this even worth doing?

Since you express concerns that the content of /etc/bashrc and /etc/profile might get changed I have to wonder who you think would be doing those changes. If it's the system itself, well the umask values you want to use are the defaults anyway so I can't see the system changing those to anything else. On the other hand, if you've got a gremlin or another sudoer who fiddles with those files...

It's important to realize that a test which tells you the code text is already in the script tells you nothing about whether that code will be executed. It's very easy to make some subtle changes that will make your code not execute despite it being in the script.

Here's one where the code only executes if false = true (i.e., never):

if false; then

if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
  umask 002
else
  umask 022
fi

fi

This one wraps the code in a HEREDOC string which is never called.

: <<'no-umask-4u'

if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
  umask 002
else
  umask 022
fi

no-umask-4u

This one simply changes the umask after your code executes (very simple example here):

if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
  umask 002
else
  umask 022
fi

umask 077

Now what? In all of the above scenarios any programmatic test for the presence of your code text in the scripts will pass even though the code will never actually be executed (or in the case of the last one it executes but is subsequently overridden).

I realize I could just copy the entire file but would rather not disturb other changes that may have been made.

Generating a sha1 hash of the file and checking to see if it ever changes might be worth considering (it would certainly be more robust than a simple check if the code is in the file somewhere). I am curious what would be the source of the "other changes" you're concerned about.

2
  • "Why would comments appear in the middle of the if command?" -- Because the line with umask can be commented out. And anyway, who knows where someone might add comments.
    – ilkkachu
    Commented Jan 28, 2022 at 7:46
  • @ilkkachu Sure, anything can be commented out. I still don't know what would be the source of those comments becoming inserted into the command after the file was saved. The system sure wouldn't do it and I assume OP doesn't enter fugue states, which means there must be other sudoers potentially doing goofy things. Commented Jan 28, 2022 at 17:08

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.