home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / xap / xfm / xfm-1.000 / xfm-1 / xfm-1.3.2 / src / FmMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  16.5 KB  |  501 lines

  1. /*---------------------------------------------------------------------------
  2.  Module FmMain
  3.  
  4.  (c) S.Marlow 1990-92
  5.  (c) A.Graef 1994
  6.  (c) R.Vogelgesang 1994 (`Xfm.BourneShells' stuff)
  7.  
  8.  main module for file manager    
  9. ---------------------------------------------------------------------------*/
  10.  
  11. #define XFMVERSION "1.3.2"
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <signal.h>
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <ctype.h>
  19.  
  20. #ifdef _AIX
  21. #include <sys/resource.h>
  22. #endif
  23.  
  24. #include <sys/wait.h>
  25.  
  26. #include <X11/Intrinsic.h>
  27. #include <X11/StringDefs.h>
  28. #include <X11/Xaw/Cardinals.h>
  29. #include <X11/Shell.h>
  30.  
  31. #include "Am.h"
  32. #include "Fm.h"
  33.  
  34. #define XtRDisplayType "DisplayType"
  35. #define XtRSortType "SortType"
  36.  
  37. /*---------------------------------------------------------------------------
  38.   Public variables
  39. ---------------------------------------------------------------------------*/
  40.  
  41. /* program name */
  42. char *progname;
  43.  
  44. /* information about the user */
  45. UserInfo user;
  46.  
  47. /* application resource values */
  48. Resources resources;
  49.  
  50. /* application context */
  51. XtAppContext app_context;
  52.  
  53. /* Update semaphor */
  54. int freeze = False;
  55.  
  56. /*---------------------------------------------------------------------------
  57.   Command line options
  58. ---------------------------------------------------------------------------*/
  59.  
  60. static XrmOptionDescRec options[] = {
  61.   { "-appmgr", ".appmgr", XrmoptionNoArg, "True" },
  62.   { "-filemgr", ".filemgr", XrmoptionNoArg, "True" },
  63.   { "-version", ".version", XrmoptionNoArg, "True" }
  64. };
  65.  
  66. /*---------------------------------------------------------------------------
  67.   Application Resources
  68. ---------------------------------------------------------------------------*/
  69.  
  70. static XtResource resource_list[] = {
  71.   { "appmgr", "Appmgr", XtRBoolean, sizeof(Boolean),
  72.       XtOffsetOf(Resources, appmgr), XtRImmediate, (XtPointer) False },
  73.   { "filemgr", "Filemgr", XtRBoolean, sizeof(Boolean),
  74.       XtOffsetOf(Resources, filemgr), XtRImmediate, (XtPointer) False },
  75.   { "version", "Version", XtRBoolean, sizeof(Boolean),
  76.       XtOffsetOf(Resources, version), XtRImmediate, (XtPointer) False },
  77.   { "initGeometry", "InitGeometry", XtRString, sizeof(String),
  78.       XtOffsetOf(Resources, init_geometry), XtRString, NULL },
  79.   { "iconFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
  80.       XtOffsetOf(Resources, icon_font), XtRString, XtDefaultFont },
  81.   { "buttonFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
  82.       XtOffsetOf(Resources, button_font), XtRString, XtDefaultFont },
  83.   { "menuFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
  84.       XtOffsetOf(Resources, menu_font), XtRString, XtDefaultFont },
  85.   { "labelFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
  86.       XtOffsetOf(Resources, label_font), XtRString, XtDefaultFont },
  87.   { "statusFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
  88.       XtOffsetOf(Resources, status_font), XtRString, XtDefaultFont },
  89.   { "boldFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
  90.       XtOffsetOf(Resources, bold_font), XtRString, XtDefaultFont },
  91.   { "cellFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *), 
  92.       XtOffsetOf(Resources, cell_font), XtRString, XtDefaultFont },
  93.   { "appIconWidth", "Width", XtRInt, sizeof(int),
  94.       XtOffsetOf(Resources, app_icon_width), XtRImmediate, (XtPointer) 48 },
  95.   { "appIconHeight", "Height", XtRInt, sizeof(int),
  96.       XtOffsetOf(Resources, app_icon_height), XtRImmediate, (XtPointer) 40 },
  97.   { "fileIconWidth", "Width", XtRInt, sizeof(int),
  98.       XtOffsetOf(Resources, file_icon_width), XtRImmediate, (XtPointer) 48 },
  99.   { "fileIconHeight", "Height", XtRInt, sizeof(int),
  100.       XtOffsetOf(Resources, file_icon_height), XtRImmediate, (XtPointer) 40 },
  101.   { "treeIconWidth", "Width", XtRInt, sizeof(int),
  102.       XtOffsetOf(Resources, tree_icon_width), XtRImmediate, (XtPointer) 48 },
  103.   { "treeIconHeight", "Height", XtRInt, sizeof(int),
  104.       XtOffsetOf(Resources, tree_icon_height), XtRImmediate, (XtPointer) 32 },
  105.   { "bitmapPath", "Path", XtRString, sizeof(String),
  106.       XtOffsetOf(Resources, bitmap_path), XtRString, NULL },
  107.   { "pixmapPath", "Path", XtRString, sizeof(String),
  108.       XtOffsetOf(Resources, pixmap_path), XtRString, NULL },
  109.   { "applicationDataFile", "ConfigFile",  XtRString, sizeof(String),
  110.       XtOffsetOf(Resources, app_file_r), XtRString, "~/.xfm/Apps" },
  111.   { "applicationDataDir", "ConfigDir",  XtRString, sizeof(String),
  112.       XtOffsetOf(Resources, app_dir_r), XtRString, "~/.xfm" },
  113.   { "applicationDataClip", "File",  XtRString, sizeof(String),
  114.       XtOffsetOf(Resources, app_clip_r), XtRString, "~/.xfm/.XfmClip" },
  115.   { "configFile", "ConfigFile",  XtRString, sizeof(String),
  116.       XtOffsetOf(Resources, cfg_file_r), XtRString, "~/.xfm/xfmrc" },
  117.   { "devFile", "ConfigFile",  XtRString, sizeof(String),
  118.       XtOffsetOf(Resources, dev_file_r), XtRString, "~/.xfm/xfmdev" },
  119. #ifdef MAGIC_HEADERS
  120.   { "magicFile", "ConfigFile",  XtRString, sizeof(String),
  121.       XtOffsetOf(Resources, magic_file_r), XtRString, "~/.xfm/magic" },
  122. #endif
  123.   { "confirmDeletes", "Confirm", XtRBoolean, sizeof(Boolean),
  124.       XtOffsetOf(Resources, confirm_deletes), XtRImmediate, (XtPointer) True },
  125.   { "confirmDeleteFolder", "Confirm", XtRBoolean, sizeof(Boolean),
  126.       XtOffsetOf(Resources, confirm_delete_folder), XtRImmediate,
  127.       (XtPointer) True },
  128.   { "confirmMoves", "Confirm", XtRBoolean, sizeof(Boolean),
  129.       XtOffsetOf(Resources, confirm_moves), XtRImmediate, (XtPointer) True },
  130.   { "confirmCopies", "Confirm", XtRBoolean, sizeof(Boolean),
  131.       XtOffsetOf(Resources, confirm_copies), XtRImmediate, (XtPointer) True },
  132.   { "confirmOverwrite", "Confirm", XtRBoolean, sizeof(Boolean),
  133.       XtOffsetOf(Resources, confirm_overwrite), XtRImmediate,
  134.       (XtPointer) True },
  135.   { "confirmQuit", "Confirm", XtRBoolean, sizeof(Boolean),
  136.       XtOffsetOf(Resources, confirm_quit), XtRImmediate, (XtPointer) True },
  137.   { "echoActions", "Echo", XtRBoolean, sizeof(Boolean),
  138.       XtOffsetOf(Resources, echo_actions), XtRImmediate, (XtPointer) False },
  139.   { "showOwner", "ShowOwner", XtRBoolean, sizeof(Boolean),
  140.       XtOffsetOf(Resources, show_owner), XtRImmediate, (XtPointer) True },
  141.   { "showDate", "ShowDate", XtRBoolean, sizeof(Boolean),
  142.       XtOffsetOf(Resources, show_date), XtRImmediate, (XtPointer) True },
  143.   { "showPermissions", "ShowPermissions", XtRBoolean, sizeof(Boolean),
  144.       XtOffsetOf(Resources, show_perms), XtRImmediate, (XtPointer) True },
  145.   { "showLength", "ShowLength", XtRBoolean, sizeof(Boolean),
  146.       XtOffsetOf(Resources, show_length), XtRImmediate, (XtPointer) True },
  147.   { "defaultDisplayType", "DefaultDisplayType", XtRDisplayType, 
  148.       sizeof(DisplayType), XtOffsetOf(Resources, default_display_type),
  149.       XtRImmediate, (XtPointer) Icons },
  150.   { "initialDisplayType", "InitialDisplayType", XtRDisplayType, 
  151.       sizeof(DisplayType), XtOffsetOf(Resources, initial_display_type),
  152.       XtRImmediate, (XtPointer) Tree },
  153.   { "defaultSortType", "DefaultSortType", XtRSortType, 
  154.       sizeof(SortType), XtOffsetOf(Resources, default_sort_type),
  155.       XtRImmediate, (XtPointer) SortByName },
  156.   { "doubleClickTime", "DoubleClickTime", XtRInt, sizeof(int),
  157.       XtOffsetOf(Resources, double_click_time), XtRImmediate,
  158.       (XtPointer) 300 },
  159.   { "updateInterval", "UpdateInterval", XtRInt, sizeof(int),
  160.       XtOffsetOf(Resources, update_interval), XtRImmediate,
  161.       (XtPointer) 10000 },
  162.   { "defaultEditor", "DefaultEditor", XtRString, sizeof(String),
  163.       XtOffsetOf(Resources, default_editor), XtRString, NULL },
  164.   { "defaultViewer", "DefaultViewer", XtRString, sizeof(String),
  165.       XtOffsetOf(Resources, default_viewer), XtRString, NULL },
  166.   { "BourneShells", "ShellList", XtRString, sizeof(String),
  167.       XtOffsetOf(Resources, sh_list), XtRString, NULL },
  168. };
  169.  
  170. /*---------------------------------------------------------------------------
  171.  Fallback resources
  172. ---------------------------------------------------------------------------*/
  173.  
  174. static String fallback_resources[] = {
  175.   "*Command.cursor : hand2",
  176.   "*MenuButton.cursor : hand2",
  177.   "*viewport.forceBars: true",
  178.   "*popup form*bitmap.borderWidth : 0",
  179.   "*popup form*label.borderWidth : 0",
  180.   "*button box.orientation : horizontal",
  181.   "*button box.borderWidth: 0",
  182.   "*file window*viewport.borderWidth: 0",
  183.   "*viewport.icon box*Label.borderWidth : 0",
  184.   "*viewport.icon box.Command.borderWidth : 0",
  185.   "*viewport.icon box.Form.borderWidth : 0",
  186.   "*viewport.icon box*Toggle.borderWidth : 1",
  187.   "*chmod*Label.borderWidth : 0",
  188.   "*info*Label.borderWidth : 0",
  189.   "*error*Label.borderWidth : 0",
  190.   "*confirm*Label.borderWidth : 0",
  191.   "*Text*translations : #override \\n\
  192.     <Key>Return: no-op() \\n\
  193.     <Key>Linefeed : no-op() \\n\
  194.     Ctrl<Key>J : no-op() \\n",
  195.   "*Text*baseTranslations : #override \\n\
  196.     <Key>Return: no-op() \\n\
  197.     <Key>Linefeed : no-op() \\n\
  198.     Ctrl<Key>J : no-op() \\n",
  199. NULL,
  200. };
  201.  
  202. /*---------------------------------------------------------------------------
  203.   Widget argument lists
  204. ---------------------------------------------------------------------------*/
  205.  
  206. static Arg shell_args[] = {
  207.   { XtNtitle, (XtArgVal) "Applications" }
  208. };
  209.  
  210. /*-----------------------------------------------------------------------------
  211.   Signal handler - clears up Zombie processes
  212.   I'll probably extend this in the future to do something useful.
  213. -----------------------------------------------------------------------------*/
  214. static void sigcldHandler(int i)
  215. {
  216.   waitpid(-1,NULL,WNOHANG);
  217. }
  218.  
  219. static struct sigaction sigcld, sigterm;
  220.  
  221. /*---------------------------------------------------------------------------
  222.   Resource converter functions
  223. ---------------------------------------------------------------------------*/
  224.  
  225. static void CvtStringToDisplayType(XrmValue *args, Cardinal *n_args,
  226.                    XrmValue *fromVal, XrmValue *toVal)
  227. {
  228.   static DisplayType d;
  229.  
  230.   if (!strcmp(fromVal->addr, "Tree"))
  231.     d = Tree;
  232.   else if (!strcmp(fromVal->addr, "Icons"))
  233.     d = Icons;
  234.   else if (!strcmp(fromVal->addr, "Text"))
  235.     d = Text;
  236.   else {
  237.     XtStringConversionWarning(fromVal->addr, XtRDisplayType);
  238.     return;
  239.   }
  240.   
  241.   toVal->addr = (caddr_t) &d;
  242.   toVal->size = sizeof(DisplayType);
  243. }
  244.  
  245. /*---------------------------------------------------------------------------*/
  246.  
  247. static void CvtStringToSortType(XrmValue *args, Cardinal *n_args,
  248.                 XrmValue *fromVal, XrmValue *toVal)
  249. {
  250.   static SortType d;
  251.  
  252.   if (!strcmp(fromVal->addr, "SortByName"))
  253.     d = SortByName;
  254.   else if (!strcmp(fromVal->addr, "SortBySize"))
  255.     d = SortBySize;
  256.   else if (!strcmp(fromVal->addr, "SortByDate"))
  257.     d = SortByMTime;
  258.   else {
  259.     XtStringConversionWarning(fromVal->addr, XtRSortType);
  260.     return;
  261.   }
  262.   
  263.   toVal->addr = (caddr_t) &d;
  264.   toVal->size = sizeof(SortType);
  265. }
  266.  
  267. /*---------------------------------------------------------------------------
  268.   `Xfm.BourneShells' related functions  
  269. ---------------------------------------------------------------------------*/  
  270.  
  271. int shell_test(UserInfo *ui)
  272. {
  273.   int pipe_fd[2];
  274.   int p;
  275.   char val[3];
  276.  
  277.   if (pipe(pipe_fd) < 0) {
  278.     perror("Can't create pipe");
  279.     exit(1);
  280.   }
  281.  
  282.   p = fork();
  283.   if (p < 0) {
  284.     perror("Can't fork");
  285.     exit(1);
  286.   }
  287.  
  288.   if (!p) {       /* child; exec the shell w/ test args */
  289.     dup2(pipe_fd[1], fileno(stdout));
  290.     if (close(pipe_fd[0]) == -1) {
  291.       perror("(child) Can't close pipe");
  292.       exit(1);
  293.     }
  294.     execlp(ui->shell, ui->shell, "-c", "echo $*", "1", NULL);
  295.     perror("Exec failed");
  296.     exit(1);
  297.   } else {        /* parent; read and check the child's output */
  298.     if (close(pipe_fd[1]) == -1) {
  299.       perror("(parent) Can't close pipe");
  300.       exit(1);
  301.     }
  302.     val[0] = '\0';
  303.     while ((p = read(pipe_fd[0], val, 3)) < 0) {
  304.       if (errno != EINTR) {
  305.     perror("Reading child's output failed");
  306.     exit(1);
  307.       }
  308.     }
  309.     if (p == 3)
  310.       return -1;
  311.     ui->arg0flag = (val[0] != '1');
  312.     return 0;
  313.   }
  314. }
  315.  
  316. char *get_first(char *s)
  317. {
  318.   char *p;
  319.  
  320.   p = strtok(s, ",");
  321.   if (p != NULL)
  322.     while (isspace(*p))
  323.       p++;
  324.   return p;
  325. }
  326.  
  327. char *get_next()
  328. {
  329.   char *p;
  330.   
  331.   p = strtok((char *) NULL, ",");
  332.   if (p != NULL)
  333.     while (isspace(*p))
  334.       p++;
  335.   return p;
  336. }
  337.  
  338. void init_arg0flag()
  339. {
  340.   if (resources.sh_list == NULL || !strcmp(resources.sh_list, "AUTO")) {
  341.     if (shell_test(&user) == -1) {
  342.       fprintf(stderr, "Xfm.BourneShells: AUTO test failed.\n");
  343.       exit(1);
  344.     }
  345.   } else {
  346.     char *p;
  347.  
  348.     for (p = get_first(resources.sh_list); p != NULL; p = get_next()) {
  349.       if ((user.arg0flag = !strcmp(p, user.shell)))
  350.         return;
  351.     }
  352.   }
  353. }
  354.  
  355. /*---------------------------------------------------------------------------
  356.   Main function
  357. ---------------------------------------------------------------------------*/
  358.  
  359. void main(int argc, char *argv[])
  360. {
  361.   char *s;
  362.  
  363.   progname = argv[0];
  364.  
  365.   /* get some information about the user */
  366.   user.uid = getuid();
  367.   user.gid = getgid();
  368.  
  369.   if ((s = getenv("HOME")))
  370.     strcpy(user.home,s);
  371.   else
  372.     getwd(user.home);
  373.  
  374.   if ((s = getenv("SHELL")))
  375.     strcpy(user.shell,s);
  376.   else
  377.     strcpy(user.shell,"/bin/sh");
  378.  
  379.   user.umask = umask(0);
  380.   umask(user.umask);
  381.   user.umask = 0777777 ^ user.umask;
  382.  
  383.   /* initialise the application and create the application shell */
  384.  
  385.   aw.shell = XtAppInitialize(&app_context, "Xfm", options, XtNumber(options),
  386.                  &argc, argv, fallback_resources, shell_args,
  387.                  XtNumber(shell_args) );
  388.  
  389.   /* make sure we can close-on-exec the display connection */
  390.   if (fcntl(ConnectionNumber(XtDisplay(aw.shell)), F_SETFD, 1) == -1)
  391.     abortXfm("Couldn't mark display connection as close-on-exec");
  392.  
  393.   /* register resource converters */
  394.   XtAppAddConverter(app_context, XtRString, XtRDisplayType, 
  395.             CvtStringToDisplayType, NULL, ZERO);
  396.   XtAppAddConverter(app_context, XtRString, XtRSortType, 
  397.             CvtStringToSortType, NULL, ZERO);
  398.  
  399.   /* get the application resources */
  400.   XtGetApplicationResources(aw.shell, &resources, resource_list,
  401.                 XtNumber(resource_list), NULL, ZERO);
  402.  
  403.   /* -version: print version number and exit: */
  404.   if (resources.version) {
  405.     printf("xfm version %s\n", XFMVERSION);
  406.     exit(0);
  407.   }
  408.  
  409.   /* default is to launch both application and file manager */
  410.   if (!resources.appmgr && !resources.filemgr)
  411.     resources.appmgr = resources.filemgr = True;
  412.  
  413.   /* set the multi-click time */
  414.   XtSetMultiClickTime(XtDisplay(aw.shell), resources.double_click_time);
  415.  
  416.   /* initialise the utilities module */
  417.   initUtils();
  418.  
  419.   /* set up signal handlers */
  420.   sigcld.sa_handler = sigcldHandler;
  421.   sigemptyset(&sigcld.sa_mask);
  422.   sigcld.sa_flags = 0;
  423.   sigaction(SIGCHLD,&sigcld,NULL);
  424.   sigterm.sa_handler = quit;
  425.   sigemptyset(&sigterm.sa_mask);
  426.   sigterm.sa_flags = 0;
  427.   sigaction(SIGTERM,&sigterm,NULL);
  428.  
  429.   /* initialise the communications module */
  430.   initComms();
  431.  
  432.   /* check the user's shell; needs signal handlers (to avoid a zombie) */
  433.   init_arg0flag();
  434.  
  435.   /* create all the bitmaps & cursors needed */
  436.   readBitmaps();
  437.   
  438.   /* Set the icon for the application manager */
  439.   XtVaSetValues(aw.shell, XtNiconPixmap, bm[APPMGR_BM], NULL);
  440.   XtVaSetValues(aw.shell, XtNiconMask, bm[APPMGRMSK_BM], NULL);
  441.  
  442.   /* create the main popup shells */
  443.   createMainPopups();
  444.  
  445.   /* initialise the applications module & create the window */
  446.   if (resources.appmgr) {
  447.     strcpy(resources.app_file, resources.app_file_r);
  448.     fnexpand(resources.app_file);
  449.     strcpy(resources.main_app_file, resources.app_file);
  450.     strcpy(resources.app_dir, resources.app_dir_r);
  451.     fnexpand(resources.app_dir);
  452.     strcpy(resources.app_clip, resources.app_clip_r);
  453.     fnexpand(resources.app_clip);
  454.     readApplicationData(resources.app_file);
  455.     createApplicationWindow();
  456.     createApplicationDisplay();
  457.     XtRealizeWidget(aw.shell);
  458.     XSetWMProtocols(XtDisplay(aw.shell), XtWindow(aw.shell),
  459.             &wm_delete_window, 1);
  460.     XtAddEventHandler(aw.shell, (EventMask)0L, True,
  461.               (XtEventHandler)clientMessageHandler, (XtPointer)NULL);
  462.   }
  463.  
  464.   /* initialise the file windows module & create a file window */
  465.   strcpy(resources.cfg_file, resources.cfg_file_r);
  466.   fnexpand(resources.cfg_file);
  467.   strcpy(resources.dev_file, resources.dev_file_r);
  468.   fnexpand(resources.dev_file);
  469. #ifdef MAGIC_HEADERS
  470.   strcpy(resources.magic_file, resources.magic_file_r);
  471.   fnexpand(resources.magic_file);
  472. #endif
  473.   initFileWindows();
  474.   if (resources.filemgr)
  475.     newFileWindow(user.home,resources.initial_display_type,False);
  476.   resources.init_geometry = NULL;
  477.  
  478.   /* start up window refresh timer */
  479.   if (resources.update_interval > 0)
  480.     XtAppAddTimeOut(app_context, resources.update_interval, timeoutCb, NULL);
  481.  
  482.   /* collect & process events */
  483.   XtAppMainLoop(app_context);
  484. }
  485.  
  486. /*---------------------------------------------------------------------------*/
  487.  
  488. void quit()
  489. {
  490.   int d;
  491.  
  492.   for (d = 0; d < n_devices; d++)
  493.     if (devs[d].mounted) {
  494.       devs[d].mounted = 1;
  495.       umountDev(d);
  496.     }
  497.  
  498.   XtDestroyApplicationContext(app_context);
  499.   exit(0);
  500. }
  501.