Use C++ linker
[oweals/cde.git] / cde / programs / dtcreate / dtcreate.sh
1 #!/bin/ksh
2
3 #######################################################################
4 #
5 #     dtcreate
6 #
7 #     The shell-script which implements dtcreate (a.k.a. CreateAction).
8 #
9 #     Hewlett-Packard Visual User Environment
10 #
11 #     Copyright (c) 1990 Hewlett-Packard Company
12 #
13 #     @(#) $XConsortium: dtcreate.sh /main/3 1995/11/01 16:13:20 rswiston $
14 #
15 ######################################################################
16
17 #####################################################################
18 #
19 # determine_system - determines the system name and then sets
20 # the global variables _SIGUSR1 and _SIGUSR2 accordingly.
21 #
22 determine_system ()
23 {
24         sys_name=`uname`
25
26         case ${sys_name} in
27                 HP-UX)
28                         _SIGUSR1=16
29                         _SIGUSR2=17
30                         ;;
31                 AIX)
32                         _SIGUSR1=30
33                         _SIGUSR2=31
34                         ;;
35                 *)
36                         _SIGUSR1=16
37                         _SIGUSR2=17
38                         ;;
39         esac
40 }
41
42 #####################################################################
43 #
44 # getvalue accepts two arguments, the name of the resource whose
45 # value is desired and the name of the file where it is contained.
46 # The value of the resource is returned in $VALUE.
47 #
48 getvalue ()
49 {
50         VALUE=`grep $1 $2 | sed -e "s/[^:]*: *//"`
51 }
52
53 enabledialog ()
54 {
55         # Sending SIGUSR1 to the dtdialog process tells it to reenable
56         # the dialog.
57         kill -${_SIGUSR1} $1
58 }
59
60 toggleinvaliddialog ()
61 {
62         # Sending SIGIUSR2 to the dtdialog process tells it to either
63         # go to the invalid state (put up the invalid cursor) or go
64         # back to its previous state (either active or busy).
65         kill -${_SIGUSR2} $1
66 }
67
68 dismissdialog ()
69 {
70         # Sending SIGINT to the dtdialog process tells it to remove the
71         # dialog and die.
72         kill -2 $1
73 }
74
75 ##############################################################
76 #
77 # checkprocess accepts a single argument with is a process-id.
78 # If the specified process is running (as reported by ps -ef),
79 # checkprocess returns 1.  If it isn't running, checkprocess
80 # returns 0.
81 #
82 checkprocess ()
83 {
84         RUNNING=`ps -ef | cut -c 9-14 | grep -c $1`
85
86         if [ "$RUNNING" = "0" ] ; then
87                 return 0
88         else
89                 return 1
90         fi
91 }
92
93 # This is the main callback that is called whenever the user presses
94 # one of the buttons on the CreateAction dialog.
95 actioncallback ()
96 {
97         # Check which button on the dialog was invoked.  The Help button
98         # is automatically handled by dtdialog, so it is only the apply
99         # and close buttons that we care about.
100         getvalue selectedButton $DIALOG_OUTPUT
101
102         if [ "$VALUE" = "apply" ] ; then
103                 checkactionvalues
104         else
105                 cleanupandexit
106         fi
107 }
108
109 checkactionvalues ()
110 {
111         # Read all the values in from the dialog.
112         getvalue windowId $DIALOG_OUTPUT
113         CREATEACTION_WID=$VALUE
114
115         getvalue name.text $DIALOG_OUTPUT
116         ACTION=$VALUE
117
118         getvalue largeIcon.text $DIALOG_OUTPUT
119         LICON=$VALUE
120
121         getvalue smallIcon.text $DIALOG_OUTPUT
122         SICON=$VALUE
123
124         getvalue description.text $DIALOG_OUTPUT
125         DESCRIPTION=`echo $VALUE | tr -s "\012" " "`
126
127         getvalue commandLine.text $DIALOG_OUTPUT
128         EXECSTRING=$VALUE
129
130         getvalue prompt.text $DIALOG_OUTPUT
131         PROMPT=$VALUE
132
133         getvalue commandType.active $DIALOG_OUTPUT
134         if [ "$VALUE" = "xWin" -o "$VALUE" = "noOut" ] ; then
135                 WINDOWTYPE="NO_STDIO"
136         elif [ "$VALUE" = "term" ] ; then
137                 WINDOWTYPE="PERM_TERMINAL"
138         else
139                 WINDOWTYPE="TERMINAL"
140         fi
141
142         BAIL_OUT=""
143         # Make sure that an action name and an exec-string were provided.
144         if [ ! "$BAIL_OUT" -a ! "$ACTION" -a ! "$EXECSTRING" ] ; then
145                 dtdialog -descFile dtcreate.ddf -dialogName noNameOrExec \
146                         -transientFor $CREATEACTION_WID &
147                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
148                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
149                 enabledialog $CREATEACTION_PID
150                 BAIL_OUT="yes"
151         fi
152
153         if [ ! "$BAIL_OUT" -a ! "$ACTION" ] ; then
154                 dtdialog -descFile dtcreate.ddf -dialogName noName \
155                         -transientFor $CREATEACTION_WID &
156                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
157                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
158                 enabledialog $CREATEACTION_PID
159                 BAIL_OUT="yes"
160         fi
161
162         if [ ! "$BAIL_OUT" -a ! "$EXECSTRING" ] ; then
163                 dtdialog -descFile dtcreate.ddf -dialogName noExecString \
164                         -transientFor $CREATEACTION_WID &
165                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
166                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
167                 enabledialog $CREATEACTION_PID
168                 BAIL_OUT="yes"
169         fi
170
171         # Make sure the action name does not contain any blanks.
172         if [ ! "$BAIL_OUT" -a `echo $ACTION | grep -c ' '` -eq 1 ] ; then
173                 dtdialog -descFile dtcreate.ddf -dialogName foundBlank \
174                         -transientFor $CREATEACTION_WID &
175                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
176                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
177                 enabledialog $CREATEACTION_PID
178                 BAIL_OUT="yes"
179         fi
180
181         if [ ! "$BAIL_OUT" ] ; then
182                 # Check the vf file we want to write to.  If it exists and
183                 # isn't writable, complain.
184                 VF_DIR=$HOME/.dt/types
185                 # Hack warning! Do temporary dt stuff.
186                 if [[ $doDT = 1 ]] then
187                   VF_FILE=$VF_DIR/$ACTION.dt
188                 else
189                   VF_FILE=$VF_DIR/$ACTION.vf
190                 fi
191                 if [ -f $VF_FILE -a ! -w $VF_FILE ] ; then
192                         dtdialog -descFile dtcreate.ddf \
193                                 -dialogName notWritable \
194                                 -transientFor $CREATEACTION_WID \
195                                 $VF_FILE &
196                         SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
197                         let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
198                         enabledialog $CREATEACTION_PID
199                         BAIL_OUT="yes"
200                 fi
201         fi
202
203         # Check if the action name is longer than 11 characters.
204         # If so, warn about the problems with short filename
205         # systems and give the user a chance to change it.  This is a
206         # modal dialog (not run in background) because the user has to
207         # make a choice.
208         if [ ! "$BAIL_OUT" -a `echo $ACTION | wc -c` -gt 11 ] ; then
209                 toggleinvaliddialog $CREATEACTION_PID
210                 dtdialog -descFile dtcreate.ddf \
211                         -dialogName longName \
212                         -transientFor $CREATEACTION_WID $ACTION
213
214                 if [ $? -eq 2 ] ; then
215                         enabledialog $CREATEACTION_PID
216                         BAIL_OUT="yes"
217                 else
218                         toggleinvaliddialog $CREATEACTION_PID
219                 fi
220         fi
221
222         # Check that if the exec-string uses any shell features (e.g. pipes),
223         # that a shell is explicitly specified.
224         if [ ! "$BAIL_OUT" -a `echo $EXECSTRING | grep -c '[|&;<>]'` -eq 1 -a\
225              ! `echo $EXECSTRING | grep -c 'sh '` -eq 1 ] ; \
226            then
227                 dtdialog -descFile dtcreate.ddf -dialogName needShell \
228                         -transientFor $CREATEACTION_WID &
229                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
230                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
231                 enabledialog $CREATEACTION_PID
232                 BAIL_OUT="yes"
233         fi
234
235         # Check that the prompt string does not contain quotes.  I
236         # think there is a bug here that a single backquote (`) is not
237         # detected.  I need to figure out the correct grep expression
238         # to catch it.
239         QUOTES=`echo \'$PROMPT\' | tr '!$%&(-\\\/"' '%%%%%%%%%' | fgrep -c %`
240         if [ ! "$BAIL_OUT" -a $QUOTES -eq 1 ] ; then
241                 dtdialog -descFile dtcreate.ddf \
242                         -transientFor $CREATEACTION_WID \
243                         -dialogName promptQuote &
244                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
245                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
246                 enabledialog $CREATEACTION_PID
247                 BAIL_OUT="yes"
248         fi
249
250         # Check that if a prompt is supplied, that the action calls for
251         # arguments.
252         if [ ! "$BAIL_OUT" ] ; then
253                 if [ "$PROMPT" -a \
254                     `echo $EXECSTRING | grep -c "\$[*0-9]"` -eq 0 ] ; then
255                         dtdialog -descFile dtcreate.ddf \
256                                 -transientFor $CREATEACTION_WID \
257                                 -dialogName unusedPrompt &
258                         SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
259                         let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
260                         enabledialog $CREATEACTION_PID
261                         BAIL_OUT="yes"
262                 fi
263         fi
264
265         # If no errors were caught, create the action and reenable the
266         # dialog.
267         if [ ! "$BAIL_OUT" ] ; then
268                 createaction
269                 enabledialog $CREATEACTION_PID
270         fi
271 }
272
273 createaction ()
274 {
275         # If the vf file already exists, we are going to copy it to a temp
276         # file and comment out the definition for the current action.
277         # Make sure that this temp file doesn't already exist so that an old
278         # one doesn't get used by mistake.
279         OLD_FILE=/tmp/`basename $0`2_$$
280         rm -f ${OLD_FILE}
281         if [ -w $VF_FILE ] ; then
282                 sed -e "/^ACTION ${ACTION}[     ]*$/,/^[END|}]/s/^/\# /" \
283                         ${VF_FILE} > ${OLD_FILE}
284         fi
285
286         # Write out the new action definition.
287         echo "\n#\n# Action created by dtcreate\n#" > $VF_FILE
288         echo "ACTION $ACTION" > $VF_FILE
289         echo "{" >> $VF_FILE
290
291         if [ "${LICON}" ] ; then
292                 echo "\tLARGE_ICON\t\t$LICON" >> $VF_FILE
293         fi
294
295         if [ "${SICON}" ] ; then
296                 echo "\tSMALL_ICON\t\t$SICON" >> $VF_FILE
297         fi
298
299         if [ "${DESCRIPTION}" ] ; then
300                 echo "\tDESCRIPTION\t$DESCRIPTION" >> $VF_FILE
301         fi
302
303         echo "\tTYPE\t\tCOMMAND" >>$VF_FILE
304
305         if [ "${EXECSTRING}" ] ; then
306                 # Process the exec-string and look for $*, $1, $2, etc.
307                 # These must be translated into DT's syntax of
308                 # %(File)Arg_n%.  Also insert the prompt string if one
309                 # was supplied.
310                 echo "\tEXEC_STRING\t\c" >>$VF_FILE
311                 if [ "$PROMPT" ] ; then
312                         echo $EXECSTRING | sed \
313                           -e "s/\$\*/%(File)Arg_1\"$PROMPT\"% %(File)Args%/" \
314                           -e "s/\$\([1-9]\)/%(File)Arg_\1\"$PROMPT\"%/" \
315                           -e "s/\$\([1-9]\)/%(File)Arg_\1%/g" \
316                                 >> $VF_FILE
317                 else
318                         echo $EXECSTRING | sed \
319                                 -e "s/\$\*/%(File)Args%/g" \
320                                 -e "s/\$\([1-9]\)/%(File)Arg_\1%/g" >> $VF_FILE
321                 fi
322         fi
323
324         if [ "${WINDOWTYPE}" ] ; then
325                 echo "\tWINDOW_TYPE\t$WINDOWTYPE" >> $VF_FILE
326         fi
327
328         echo "}" >>$VF_FILE
329
330         # If the temp file with the old contents of the vf file exists,
331         # stick it on the end of the file we just created.
332         if [ -r ${OLD_FILE} ] ; then
333                 echo "\n#\n# Commented out by dtcreate\n#" >> $VF_FILE
334                 cat ${OLD_FILE} >> ${VF_FILE}
335                 rm ${OLD_FILE}
336         fi
337
338         #
339         # Invoke ReloadActions so that the new action
340         # will be read.
341         dtaction -timeout 1 ReloadActions
342
343         #
344         # Create the action copy file in the home directory.
345         if [ -w ${TOOLBOX} -a ! -f ${TOOLBOX}/${ACTION} ] ; then
346                 touch ${TOOLBOX}/${ACTION}
347                 chmod 755 ${TOOLBOX}/${ACTION}
348         fi
349
350         # Check whether the action exists in the Home directory.  (Either we
351         # just created it or it may have already existed.)
352         if [ -x ${TOOLBOX}/${ACTION} ] ; then
353                 dtdialog -descFile dtcreate.ddf -dialogName actionExists \
354                         -transientFor $CREATEACTION_WID \
355                         $ACTION $VF_FILE &
356                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
357                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
358         else
359                 dtdialog -descFile dtcreate.ddf \
360                         -dialogName actionDoesntExist \
361                         -transientFor $CREATEACTION_WID \
362                         $ACTION $VF_FILE &
363                 SECONDARY_DIALOG_PIDS[${NUM_SECONDARY_DIALOGS}]=$!
364                 let NUM_SECONDARY_DIALOGS=${NUM_SECONDARY_DIALOGS}+1
365         fi
366 }
367
368 cleanupandexit()
369 {
370         # Dismiss any secondary dialogs (e.g. Help, warnings, errors)
371         # that have been created.
372         if [ NUM_SECONDARY_DIALOGS -gt 0 ]; then
373                 for PID in ${SECONDARY_DIALOG_PIDS[*]}
374                 do
375                         checkprocess $PID
376                         if [ $? -eq 1 ] ; then
377                                 dismissdialog $PID
378                         fi
379                 done
380         fi
381
382         dismissdialog $CREATEACTION_PID
383
384         rm -f ${DIALOG_OUTPUT}
385 }
386
387
388 #####################################################################
389 # Main
390 #
391 #set -xv
392 DIALOG_OUTPUT=/tmp/`basename $0`$$
393 #TOOLBOX=$HOME/.dt/types/tools
394 TOOLBOX=$HOME
395 NUM_SECONDARY_DIALOGS=0
396
397 determine_system
398
399 # Hack warning:  This is to determine if should create .dt file or .vf file.
400 if [[ -f /opt/dt/types/useFT ]] then
401   doDT=0
402 else
403   doDT=1
404 fi
405
406 # Set up the callback function that is invoked when the user
407 # presses any of the dialog buttons.
408 trap "actioncallback" ${_SIGUSR1}
409
410 # Invoke dtdialog and pass in the process-ID of this script.
411 # When the user presses any of the dialog buttons, dtdialog
412 # will send us a signal which will cause the callback function
413 # to be called.
414 PARENT_PID=$$
415 dtdialog -descFile dtcreate.ddf -dialogName createAction -returnWinId \
416         -signal SIGUSR1 -ppid $PARENT_PID -outFile $DIALOG_OUTPUT &
417
418 # Keep track of the process-ID of the dtdialog process that is
419 # managing the main CreateAction dialog.  We need this process-ID so
420 # that we can send it signals to do things such as reenable it.
421 CREATEACTION_PID=$!
422
423 # Sit in a loop as long as the main CreateAction dialog is up.  The
424 # signals cause the 'wait' call to exit and I don't know of any way to
425 # determine whether the wait existed due to a signal or because the
426 # process died.  Therefore we have to explicitly check if the process
427 # is alive.
428 EXIT=0
429 while [ $EXIT -eq 0 ] ; do
430         wait $CREATEACTION_PID
431         checkprocess $CREATEACTION_PID
432         if [ $? -eq 0 ] ; then
433                 EXIT=1
434         fi
435 done
436
437 exit 0
438
439