/***************************************************************************/ /***************************************************************************/ /* */ /* (c) 1995-1999. The Regents of the University of California. All */ /* rights reserved. */ /* */ /* This work was produced at the University of California, Lawrence */ /* Livermore National Laboratory (UC LLNL) under contract no. */ /* W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy */ /* (DOE) and The Regents of the University of California (University) */ /* for the operation of UC LLNL. Copyright is reserved to the */ /* University for purposes of controlled dissemination, */ /* commercialization through formal licensing, or other disposition */ /* under terms of Contract 48; DOE policies, regulations and orders; */ /* and U.S. statutes. The rights of the Federal Government are */ /* reserved under Contract 48 subject to the restrictions agreed upon */ /* by the DOE and University. */ /* */ /* */ /* DISCLAIMER */ /* */ /* This software was prepared as an account of work sponsored by an */ /* agency of the United States Government. Neither the United States */ /* Government nor the University of California nor any of their */ /* employees, makes any warranty, express or implied, or assumes any */ /* liability or responsibility for the accuracy, completeness, or */ /* usefulness of any information, apparatus, product, or process */ /* disclosed, or represents that its specific commercial products, */ /* process, or service by trade name, trademark, manufacturer, or */ /* otherwise, does not necessarily constitute or imply its */ /* endorsement, recommendation, or favoring by the United States */ /* Government or the University of California. The views and opinions */ /* of the authors expressed herein do not necessarily state or reflect */ /* those of the United States Government or the University of */ /* California, and shall not be used for advertising or product */ /* endorsement purposes. */ /* */ /* Permission to use, copy, modify and distribute this software and its */ /* documentation for any non-commercial purpose, without fee, is */ /* hereby granted, provided that the above copyright notice and this */ /* permission notice appear in all copies of the software and */ /* supporting documentation, and that all UC LLNL identification in */ /* the user interface remain unchanged. The title to copyright LLNL */ /* XDIR shall at all times remain with The Regents of the University */ /* of California and users agree to preserve same. Users seeking the */ /* right to make derivative works with LLNL XDIR for commercial */ /* purposes may obtain a license from the Lawrence Livermore National */ /* Laboratory's Technology Transfer Office, P.O. Box 808, L-795, */ /* Livermore, CA 94550. */ /* */ /***************************************************************************/ /***************************************************************************/ #include #include #include #include #include #include #include "xdir.h" #include "list.h" #include "str.h" #define MAXARGV 300 static struct { struct dirwin_st *dirwin; struct entry_link *head; } lc; struct dirwin_st *launch_dirwin; extern struct sl_struct *launcher_mappings; extern XtAppContext app; extern struct st_host_info hinfo[]; extern int beep_when_ops_done; extern int child_to_parent_pipe[]; extern struct dirwin_st *dirwin_head; #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__GNU_LIBRARY__) && !defined(__GLIBC__) && !defined(__EMX__) extern char *sys_errlist[]; #endif char *entry_to_full_path(); struct sl_struct *create_array_list(); int cb_launch_commands(); char *system_name(); char *server_name(); char *decrypt_password(); char *cstring_to_text(); void concat(); void update_launch_menus(); /* * cb_launch - Callback to launch the command selected in the "Launch" * menu. */ void cb_launch(widget, client_data, call_data) Widget widget; XtPointer client_data; XtPointer call_data; { struct dirwin_st *dirwin = (struct dirwin_st *)client_data; XmString string; char *command_name; char *raw_command_line; char *command_line; char *ptr; int found_percent; int found_percent_s; int found_percent_l; int len; int i; int j; int k; char ch; struct entry_link *head_selected_entries = NULL; struct entry_link *head_command_lines = NULL; char *full_path; struct sl_struct *list; char buf[2]; int nlaunches; char *passwrd; /* Start operation */ if (!start_op(True)) return; /* Clear error flag */ raise_okflag(); XtVaGetValues(widget, XmNlabelString, &string, NULL); command_name = cstring_to_text(string); XmStringFree(string); /* Yes, this is necessary */ /* Get command line associated with command name */ for (i=0; inentries; i++) if (!compare_command_names(command_name, launcher_mappings->entries[i])) break; if (i == launcher_mappings->nentries) fatal_error("Bug in cb_launch()"); if ((ptr = strchr(launcher_mappings->entries[i], ':')) == NULL) fatal_error("Bug in cb_launch()"); XtFree(command_name); raw_command_line = ptr+2; /* Create list of full paths of selected entries */ for (i=0; inentries; i++) if (dirwin->entries[i].state == SELECTED) { full_path = entry_to_full_path(&dirwin->entries[i]); add_to_linked_list(&head_selected_entries, full_path); XtFree(full_path); } list = create_array_list(&head_selected_entries); /* Are %l and/or %s present in command line? */ found_percent = False; found_percent_s = False; found_percent_l = False; len = strlen(raw_command_line); for (j=0; jnentries == 0) && (found_percent_s || found_percent_l)) { warn("Can't launch command -- Requires selected entries.", dirwin->w_shell); release_array_list(list); end_op(); return; } /* Interpret command line and create actual command line(s) */ if (found_percent_s) nlaunches = list->nentries; else nlaunches = 1; for (i=nlaunches-1; i>=0; i--) { found_percent = False; len = strlen(raw_command_line); command_line = XtNewString(""); for (j=0; jhost].hostname); break; case 'u': concat(&command_line, hinfo[dirwin->host].username); break; case 's': concat(&command_line, list->entries[i]); break; case 'l': for (k=0; knentries; k++) { concat(&command_line, list->entries[k]); if (k != list->nentries-1) concat(&command_line, " "); } break; case 'y': concat(&command_line, system_name(hinfo[dirwin->host].system)); break; case 'v': concat(&command_line, server_name(hinfo[dirwin->host].server)); break; case 'p': if (hinfo[dirwin->host].password) { passwrd = decrypt_password(hinfo[dirwin->host].password); concat(&command_line, passwrd); bzero(passwrd, (int)strlen(passwrd)); XtFree(passwrd); } else concat(&command_line, "NO_PASSWORD"); break; default: buf[0] = ch; buf[1] = '\0'; concat(&command_line, buf); } found_percent = False; } else if (ch == '%') found_percent = True; else { buf[0] = ch; buf[1] = '\0'; concat(&command_line, buf); } } if (found_percent) concat(&command_line, "%"); add_to_linked_list(&head_command_lines, command_line); XtFree(command_line); } /* Construct control block for launch commands */ lc.dirwin = dirwin; lc.head = head_command_lines; release_array_list(list); /* Pop up launch monitor */ show_mp_monitor(dirwin, "Now Launching:"); /* Make operation interruptable */ show_stop_button(dirwin); /* Launch commands */ XtAppAddWorkProc(app, (XtWorkProc)cb_launch_commands, NULL); } /* * init_launch_menus - Create the popup launch menu and then initialize the * popup and pulldown launch menus by creating a bunch * of placeholder menu items. */ void init_launch_menus(dirwin) struct dirwin_st *dirwin; { XmString string; int i; Widget w_pulldown; /* Get pulldown menu */ XtVaGetValues(dirwin->w_launchMenu, XmNsubMenuId, &w_pulldown, NULL); /* Create popup menu */ dirwin->w_popupLaunchMenu = XmCreatePopupMenu(dirwin->w_drawingArea, "popup", NULL, 0); /* Create header for popup menu */ XtVaCreateManagedWidget("popupLaunchMenuLabel", xmLabelGadgetClass, dirwin->w_popupLaunchMenu, NULL); XtVaCreateManagedWidget("separator", xmSeparatorGadgetClass, dirwin->w_popupLaunchMenu, NULL); XtVaCreateManagedWidget("separator", xmSeparatorGadgetClass, dirwin->w_popupLaunchMenu, NULL); /* Now create the menu items, but leave them unmanaged */ string = XmStringCreateSimple("Dummy"); for (i=0; iw_launchMenuItem[i] = XtVaCreateWidget( "", xmPushButtonGadgetClass, w_pulldown, XmNlabelString, string, NULL ); XtAddCallback(dirwin->w_launchMenuItem[i], XmNactivateCallback, cb_launch, (XtPointer)dirwin); dirwin->w_popupLaunchMenuItem[i] = XtVaCreateWidget( "", xmPushButtonGadgetClass, dirwin->w_popupLaunchMenu, XmNlabelString, string, NULL ); XtAddCallback(dirwin->w_popupLaunchMenuItem[i], XmNactivateCallback, cb_launch, (XtPointer)dirwin); } XmStringFree(string); } /* * update_all_launch_menus - Update the "Launch" menu in each directory * window. */ void update_all_launch_menus() { struct dirwin_st *dirwin; dirwin = dirwin_head; while (dirwin) { update_launch_menus(dirwin); dirwin = dirwin->next; } } /* * update_launch_menus - Update the popup and pulldown launch menus with * the latest values from the launch preferences. */ void update_launch_menus(dirwin) struct dirwin_st *dirwin; { int i; XmString label; char *temp_buf; char *command_name; /* Get rid of current launch menus items */ for (i=0; iw_launchMenuItem[i]); XtUnmanageChild(dirwin->w_popupLaunchMenuItem[i]); } /* Set sensitivity of launch menu */ if (launcher_mappings->nentries) XtSetSensitive(dirwin->w_launchMenu, True); else XtSetSensitive(dirwin->w_launchMenu, False); /* Enter launch command names into launch menus */ for (i=0; inentries; i++) { temp_buf = XtNewString(launcher_mappings->entries[i]); command_name = strtok(temp_buf, ":"); label = XmStringCreateSimple(command_name); XtFree(temp_buf); XtVaSetValues(dirwin->w_launchMenuItem[i], XmNlabelString, label, NULL); XtVaSetValues(dirwin->w_popupLaunchMenuItem[i], XmNlabelString, label, NULL); XmStringFree(label); XtManageChild(dirwin->w_launchMenuItem[i]); XtManageChild(dirwin->w_popupLaunchMenuItem[i]); } } /* * concat - Concatenates string "s2" to string "s1". "s1" is actually a * pointer to a string. The original string pointed to by "s1" * is freed with XtFree(). Use XtFree() to release the memory * returned in "s2". */ void concat(s1, s2) char **s1; char *s2; { char *new_s1 = XtMalloc(strlen(*s1)+strlen(s2)+1); strcpy(new_s1, *s1); strcat(new_s1, s2); XtFree(*s1); *s1 = new_s1; } /* * cb_launch_commands - Work proc to actually launch commands. */ cb_launch_commands() { struct entry_link *ptr; int pid; char *argv[MAXARGV+1]; int argc; char *cmd; char *msg; int saved_errno; int len; /* Did user push stop button? */ if (stop()) { goto abort; } /* Are we done? */ if (lc.head == NULL) goto done; /* Let user know where we are */ update_mp_monitor(lc.head->entry); /* Parse execute line into tokens */ cmd = XtNewString(lc.head->entry); argc = 0; if ((argv[argc++] = strtok(cmd, " ")) == NULL) fatal_error("Trouble in cb_launch_commands()"); while (argc < MAXARGV && (argv[argc] = strtok(NULL, " ")) != NULL) argc++; if (argc == MAXARGV) { warn("Can't launch command -- Bad execute line", lc.dirwin->w_shell); XtFree(cmd); goto done; } /* Fork and exec */ launch_dirwin = lc.dirwin; if ((pid = fork()) == 0) if (execvp(argv[0], argv) == -1) { saved_errno = errno; msg = XtMalloc(50+strlen(lc.head->entry)+ strlen(sys_errlist[saved_errno])); sprintf(msg, "Unable to launch command:\n\n%s\n\n", lc.head->entry); strcat(msg, sys_errlist[saved_errno]); strcat(msg, "\n\007"); len = strlen(msg); if (iwrite(child_to_parent_pipe[1], msg, len) != len) fatal_error("Trouble in cb_launch_commands()"); exit(-1); } /* Finished launching this command */ XtFree(cmd); ptr = lc.head; lc.head = lc.head->next; XtFree(ptr->entry); XtFree((char *)ptr); sleep(1); return False; abort: hide_mp_monitor(); record_abort("Launch Command"); goto final; done: hide_mp_monitor(); final: /* Miscellaneous cleanup */ release_linked_list(&lc.head); if (beep_when_ops_done) beep(); restore_prev_cursor(); /* Signal end of operation */ hide_stop_button(); end_op(); return True; }