2

Details

OS: Solaris 10 , update 11
HW: M5-32 LDOM, V490, IBM x3650, T5240, VMware virtual machine, etc...
EDITOR=vi
term=vt100
tmp directory=/var/tmp
cron shell=/sbin/sh
My shell=/bin/bash

Issue

A very interesting error occurs when attempting to modify the crontab via crontab -e.

If I attempt to search for a non-existent string utilizing crontab -e to verify and check syntax with vi as my editor, and then try and save, it will puke back and tell me an error has occurred even if no changes were made.

Example

admin@server# export EDITOR=vi
admin@server# crontab -e

In command mode, search for a non-existent string like "foobar123". After receiving the "Pattern not found" then attempt to :wq and you'll receive...

The editor indicates that an error occurred while you were
    editing the crontab data - usually a minor typing error.
Edit again, to ensure crontab information is intact (y/n)?
('n' will discard edits.)

If you are cheeky and choose to go right back in and attempt to save it will now save sans error. This is repeatable from on all types of Solaris from VMware to M5-32 LDOM, to a V490 physical. Curious as to why cron would interpret a search for a non-existent string as an error, but not say visudo.

A related note is Solaris 11 will not produce this error, which then begs the question if this is some sort of POSIX specification why it would apply to Solaris 10 and not 11?

  • What happens if you don't do anything in the editor (that is, don't search for any strings) and instead immediately :wq? What happens if you use a different EDITOR besides vi? I'm thinking that vi has a tendency to add a newline to the end of the file if there isn't one already, and this might somehow be the source of your issue. – jayhendren Nov 28 '16 at 18:43
  • Oh, I guess I missed part of your question. It appears that the newline at the end of the crontab file is not an issue. I have a Solaris 10 box handy; I'll see if I can reproduce the issue. – jayhendren Nov 28 '16 at 18:46
  • Sadly we only have vi and ed on our Solaris boxes. There is no vim, emacs, pico, etc... so it's been hard to verify if vi is the real problem child here.

    If I search for nothing and save, it will save without producing any error. Whether you make edits or don't doesn't affect it saving correctly until you attempt that non-existent search. A search for an existing string and then :wq will also save correctly.

    EDIT: Just saw that vi is a link to vim on Solaris 11 which would tend to support a vi specific issue. Tried on about 20 systems so far all with the same result.

    – Sending_Grounds Nov 28 '16 at 18:49
  • I am able to reproduce on Solaris 10. I'm poking into this a little bit here and there but I don't have much free time today. I'll let you know if I find anything. – jayhendren Nov 28 '16 at 19:14
  • Thanks! If nothing else, nice to know it's not just our environment to help limit the factors of searching into. – Sending_Grounds Nov 28 '16 at 19:16
  • The failed search appears to be setting the exit code of vi to 1 (non-zero), which crontab is likely picking up on. – Jeff Schaller Nov 28 '16 at 19:28
  • possibly related: http://unix.stackexchange.com/a/293461/117549 – Jeff Schaller Nov 28 '16 at 19:38
  • posix page for ex (vi) leaves it pretty generic for the exit code: "The following exit values shall be returned: 0 Successful completion.; >0 An error occurred." – Jeff Schaller Nov 28 '16 at 19:46
  • @JeffSchaller Good call, verified that other attempt with :Wq and some other variations in vi to the same effect; vi returns a non-zero for almost any bad command in command mode.

    Which explains why when you say 'y' and reopen the crontab and immediately save, it's a new session with a different exit code of '0' and therefore cron allows you to continue.

    Strange that visudo doesn't have similar behavior, or maybe sudo doesn't care about the return value of vi the same way cron does.

    – Sending_Grounds Nov 28 '16 at 21:16
  • the latter; visudo does its own syntax-checking of the file, so it doesn't have to care about vi's exit status (whether it looks or not, I don't know) – Jeff Schaller Nov 28 '16 at 21:41

2 Answers2

1

Not having the source to Solaris 10 or Solaris 11, I can't say for sure, but I suspect that Thomas Dickey is on the right track, based on his findings with vim.

I tracked down the IllumOS source where a search for errcnt in the ex/vi directory shows that errcnt is only ever incremented, and errcnt is used as the return code from main().

Thus, any failure that increments errcnt in vi will "bubble up" to the crontab command, where the IllumOS source for crontab indicates that it will be unhappy with anything other than zero.

Notice also the comment in crontab.c!

311             ret = system(buf);
...
327             if ((ret) && (errno != EINTR)) {
328                 /*
329                  * Some editors (like 'vi') can return
330                  * a non-zero exit status even though
331                  * everything is okay. Need to check.
332                  */
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • That's one of the best comments in code I've seen in a while. Ha!

    "Hey I'm not sure if this is going to cause issues, even though nothing is wrong... someone should probably check it out. Someone whose not me, that is."

    Perfect; combined with the above about vi equaling a sym link to vim on Solaris 11, and your explanation on sudoers doing it's own syntax checking... I think this closes the case.

    – Sending_Grounds Dec 01 '16 at 13:25
-1

OS: Solaris 10 , update 11 HW: LDOM, VMware virtual machine, etc... EDITOR=vi term=vt100

My observations in the behavior of vi and crontab is similar to the above. Crontab -e giving the error "The editor indicates that an error occurred while you were editing the crontab data ....."

and you have no choice but to either edit again and again...or throw away the changes. And using vi editor to make changes to any file and trying to save will only throw the changes away. I think vi is the culprit for crontab's behavior as well. I have now a wrapper script for vi to force it to exit with a zero exit status so vi can save the changes to the edited files. And I redirect crontab contents to a file and edit the changes in the file and redirect it back to crontab. A little painful and annoying but works until we get to solaris 11.NK