You’re passing the password to the do shell script, so unless sudo requires another user than the current shell user, you will be never prompted until you recompile the script. But when you’re not in the sudoer’s list, you will be prompted again, so therefore it’s wise when you send the password, you also send the username where the password is for. Because you aren’t guaranteed that the user running the script will be match the user you’re providing the password for. It depends on the user who is running the process that contains the running instance of AppleScript (user of current application).
do shell script "echo 'hello world!'" user name "<shortname>" password "<password>" with administrator privileges
Slightly off topic, I liked the usage of exist for checking if a property has been intialized, and wanted to replicate it for global variables, since the usage of exists doesn’t work before a global has been assigned a missing value.
global tp
set tp to assert(a reference to tp, missing value)
log tp
on assert(avar, initval)
(*
The assert handler takes advantage of the fact that a script will throw an error if you assign a value from an unasigned variable to another. (Naturally). If that error is thrown, then we set a value to the variable we want to assert that have a value in the error clause of the try block.
Otherwise if everything is ok, (the variable we want to assert has a value does have one), we just return the value the variable already had.
We have to return a value though, because the reference won't work, as long as no value is assigned to the variable we want to assert has a value.
The reason for using a reference is that we do need to pass the variable by a reference, since we otherwise will get the unassigned error thrown the moment we try to pass the unassigned variable to the handler. -Which alleviates the need for a handler, but leads to lot of clutter and repeated code if you need to assert more than one variable.
*)
try
set dummy to contents of avar
on error
return initval
end try
return contents of avar
end assert
What a coincidence. I was just looking at the ‘do shell script’ parameters and was wondering why you would want to add the administrator name! What you say makes a lot of sense. Thanks.
Hi McUsr,
Tricky script! I need to look at that again. Thanks.
Have a good day what ever is left of it on that side of the world.
Thanks a lot,
kel
ps. I’ve been trying to sum up everything while driving this morning. Think i have it.
Here’s the final template script if anyone is interested:
property pw : missing value
property admin_name : "kelhome"
-- if first run then get the passwd
if (pw is missing value) then
display dialog "Enter password for " & admin_name & ":" default answer ""
set pw to text returned of result
end if
-- set seconds to add to current date for target date
set targ_secs to 1 * minutes
set cur_date to current date
set target_date to (cur_date + targ_secs) as «class isot» as string
-- format iso time for pmset
do shell script "date -jf '%Y-%m-%dT%H:%M:%S' '" & target_date & "' '+%m/%d/%y %H:%M:%S'"
set format_date to result
-- schedule wake from computer sleep (or display sleep)
-- on first run, user must enter admin password twice
-- needs admin password once to avoid password entry dialog after timeout
-- second password dialog enters the admin info in sudoers' file
-- can adjust timeout to never (0), using visudo (see man page)
do shell script "pmset schedule wake \"" & format_date & "\"" user name admin_name password pw with administrator privileges
-- display sleep
do shell script "pmset displaysleepnow"
Added quick summary and explanation in the comments.
The script is very useful by itself, but the storing of password makes it even better. It should even be possible to make it re-enter the password for the case that you change it. And then, if the script is stored as run only, I guess it will be a little bit harder to figure out the password. (I think you can read out stored properties, and maybe variables too with Script Editor, even if they aren’t declared in the script, but I don’t think that works when the script is stored as run only.)
It’s a cobbling together from many sources including the date format from Nigel’s scripts. I was thinking about using the short version with ‘+%D %T’, but might copy and paste this format for other formats.
I’ve been wanting to clear up my password confusion for over a year, but went into the addictive video game mode for a while.
I was just thinking about a question I asked before.
When you run a program, is there a way so that on the first run you run some program and on the second run, there is no if statements or anything and the second part of the program will run. I think we found a solution. I can’t remember what the code was, but I’m sure there was a solution.
I need to search for it!
You remember, huh Nigel. Maybe we could implement that in this.
I’m starting to remember it. when you run the program, the first part runs. When you run the program again, the second part runs and has nothing to do with the first part. Darn, how did that go?
there are several solutions but they depend on the type of the script.
AppleScript Properties in applets/droplets are persistent, so define a property for example firstRun with the default value of true and set it to false when the applet launches the first time.
Unlike applets compiled scripts could be recompiled at runtime, in this case you need an external place to save the information, a script (object) using load/store script or a plist file using do shell script defaults
You reall don’t have to look any further than DJ Bazzie Wazzies test if a property exists. if it doesn’t, then the script needs to be initialized for the same time. My way does the same, but is more of a kluge really.
Both of those approaches works great if the script is to be distributed at macscripters, where the script turns up in your editor, and is compiled before it is used. If you distribute a script thru email, then you should really also test for the machine name, or some other means, so that you are sure that the script is initialized the first time it is run.
The switch examples you’re looking for is launching a handler for the first time and never again, then after that launch alway the other handler. That is a workflow that doesn’t fit right in your code because you want only user interaction when a value isn’t set.
But the actual switch in handlers is probably something like this:
theHandlerReference()
set theHandlerReference to handler2
on handler1()
display dialog "handler 1"
end handler1
on handler2()
display dialog "handler 2"
end handler2
-- we need to define the property after defining the handlers otherwise the code won't compile
property theHandlerReference : handler1
edit: Personally not my favorite because you got rid of the if-statement but still requires a setter each run. Setting (copying) an reference to a handler each run to get rid of an boolean comparison is missing the point of efficiency. Another post of mine, which has implicitly an if-then-else statement by using logic operators and and or. is maybe nicer to look at. You get something like this then:
property userPassword : missing value
property userName : missing value
set userName to do shell script "whoami"
userPassword = missing value and setUserPasword() or setPowerManagement()
on setUserPasword()
display dialog "Enter password for " & userName & ":" default answer ""
set userPassword to text returned of result
return false --return false to immediately run setPowerManagement() handler
end setUserPasword
on setPowerManagement()
-- set seconds to add to current date for target date
set targ_secs to 1 * minutes
set cur_date to current date
set target_date to (cur_date + targ_secs) as «class isot» as string
do shell script "date -jf '%Y-%m-%dT%H:%M:%S' '" & target_date & "' '+%m/%d/%y %H:%M:%S'"
set format_date to result
do shell script "pmset schedule wake \"" & format_date & "\"" user name userName password userPassword with administrator privileges
-- display sleep
do shell script "pmset displaysleepnow" --note: this command only works in 10.9 and up
return true
end setPowerManagement
Yes, that was the switcher. I see now how it sets every run. I’ll probably stick with the easy to understand method. Will look through everyones post again.