From f557ac3324534ef4da4decac9ec000db9b28e1a8 Mon Sep 17 00:00:00 2001
From: Vidar Holen <spam@vidarholen.net>
Date: Tue, 2 Jul 2013 22:37:33 -0700
Subject: [PATCH] Added check for 'exec foo; cmd'

---
 ShellCheck/Analytics.hs | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/ShellCheck/Analytics.hs b/ShellCheck/Analytics.hs
index 1cbb779..f8d448a 100644
--- a/ShellCheck/Analytics.hs
+++ b/ShellCheck/Analytics.hs
@@ -125,6 +125,7 @@ basicChecks = [
     ,checkInexplicablyUnquoted
     ,checkTildeInQuotes
     ,checkLonelyDotDash
+    ,checkSpuriousExec
     ]
 treeChecks = [
     checkUnquotedExpansions
@@ -1121,6 +1122,40 @@ checkLonelyDotDash t@(T_Redirecting id _ _)
         err id "Don't add spaces after the slash in './file'."
 checkLonelyDotDash _ = return ()
 
+
+prop_checkSpuriousExec1 = verify checkSpuriousExec "exec foo; true"
+prop_checkSpuriousExec2 = verify checkSpuriousExec "if a; then exec b; exec c; fi"
+prop_checkSpuriousExec3 = verifyNot checkSpuriousExec "echo cow; exec foo"
+prop_checkSpuriousExec4 = verifyNot checkSpuriousExec "if a; then exec b; fi"
+prop_checkSpuriousExec5 = verifyNot checkSpuriousExec "exec > file; cmd"
+prop_checkSpuriousExec6 = verify checkSpuriousExec "exec foo > file; cmd"
+checkSpuriousExec = doLists
+  where
+    doLists (T_Script _ _ cmds) = doList cmds
+    doLists (T_BraceGroup _ cmds) = doList cmds
+    doLists (T_WhileExpression _ _ cmds) = doList cmds
+    doLists (T_UntilExpression _ _ cmds) = doList cmds
+    doLists (T_ForIn _ _ _ cmds) = doList cmds
+    doLists (T_IfExpression _ thens elses) = do
+        mapM_ (\(_, l) -> doList l) thens
+        doList elses
+    doLists _ = return ()
+
+    doList t@(current:following:_) = do
+        commentIfExec current
+        doList (tail t)
+    doList _ = return ()
+
+    commentIfExec (T_Pipeline id list) =
+      mapM_ commentIfExec list
+    commentIfExec (T_Redirecting _ _ f@(
+      T_SimpleCommand id _ (cmd:arg:_))) =
+        when (f `isUnqualifiedCommand` "exec") $
+          warn (id) $
+            "Remove \"exec \" if script should continue after this command."
+    commentIfExec _ = return ()
+
+
 --- Subshell detection
 
 prop_subshellAssignmentCheck = verifyFull     subshellAssignmentCheck "cat foo | while read bar; do a=$bar; done; echo \"$a\""