001    // This file is part of the program FRYSK.
002    //
003    // Copyright 2005, Red Hat Inc.
004    //
005    // FRYSK is free software; you can redistribute it and/or modify it
006    // under the terms of the GNU General Public License as published by
007    // the Free Software Foundation; version 2 of the License.
008    //
009    // FRYSK is distributed in the hope that it will be useful, but
010    // WITHOUT ANY WARRANTY; without even the implied warranty of
011    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012    // General Public License for more details.
013    // 
014    // You should have received a copy of the GNU General Public License
015    // along with FRYSK; if not, write to the Free Software Foundation,
016    // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
017    // 
018    // In addition, as a special exception, Red Hat, Inc. gives You the
019    // additional right to link the code of FRYSK with code not covered
020    // under the GNU General Public License ("Non-GPL Code") and to
021    // distribute linked combinations including the two, subject to the
022    // limitations in this paragraph. Non-GPL Code permitted under this
023    // exception must only link to the code of FRYSK through those well
024    // defined interfaces identified in the file named EXCEPTION found in
025    // the source code files (the "Approved Interfaces"). The files of
026    // Non-GPL Code may instantiate templates or use macros or inline
027    // functions from the Approved Interfaces without causing the
028    // resulting work to be covered by the GNU General Public
029    // License. Only Red Hat, Inc. may make changes or additions to the
030    // list of Approved Interfaces. You must obey the GNU General Public
031    // License in all respects for all of the FRYSK code and other code
032    // used in conjunction with FRYSK except the Non-GPL Code covered by
033    // this exception. If you modify this file, you may extend this
034    // exception to your version of the file, but you are not obligated to
035    // do so. If you do not wish to provide this exception without
036    // modification, you must delete this exception statement from your
037    // version and license this file solely under the GPL without
038    // exception.
039    /**
040     * Used to store a pointer to the Proc object
041     * and any data that is relates to the process but is gui specific.
042     * Used to pass data to ActionPool Actions.
043     * Actions also manipulate data stored in here
044     * to keep it up to date.
045     * for example the Attach action will set proc from null
046     * to point to the Proc object returned by the backend
047     * attach function.
048     */
049    package frysk.gui.monitor;
050    
051    import java.io.File;
052    import java.util.HashMap;
053    
054    import frysk.proc.Manager;
055    import frysk.proc.Proc;
056    
057    /**
058     * TODO To change the template for this generated type comment go to
059     * Window - Preferences - Java - Code Style - Code Templates
060     */
061    public class GuiProc extends GuiCoreObjectWrapper{
062            
063            public static final String PATH_NOT_FOUND = "*Could not retrieve path*";
064    
065            private Proc proc;
066            
067            private String executableName;
068            private String executablePath;
069            private String niceExecutablePath;
070            
071            public GuiObservable executablePathChanged;
072            
073        public GuiProc(Proc proc){
074          
075          if(proc == null){
076            throw new IllegalArgumentException("proc cannot be null");
077          }
078          this.proc = proc;
079            
080          this.executablePathChanged = new GuiObservable();
081          
082          this.executableName = "";
083    
084          this.setExecutablePath();
085          this.setNiceExecutablePath();
086        }
087    
088        public Proc getProc() {
089          return proc;
090        }
091            
092        private void setNiceExecutablePath(){
093                    
094          this.niceExecutablePath = this.getFullExecutablePath();
095    
096          if(niceExecutablePath.indexOf('\0') != -1){
097            niceExecutablePath = niceExecutablePath.substring(0,niceExecutablePath.indexOf("\0"));
098          }
099    
100          if(niceExecutablePath.endsWith(" (deleted)")){
101            niceExecutablePath = niceExecutablePath.substring(0,niceExecutablePath.indexOf(" (deleted)"));
102          }
103                    
104          if(niceExecutablePath.indexOf(".#prelink#") != -1){
105            niceExecutablePath = niceExecutablePath.substring(0,niceExecutablePath.indexOf(".#prelink#"));
106          }
107                    
108          if(this.executablePath == PATH_NOT_FOUND){
109            this.executableName = proc.getCommand();
110          }else{
111            File file = new File(niceExecutablePath);               
112            this.executableName = file.getName();
113          }
114        }
115    
116        /**
117         * The executable path of a proc might be mangled with things like '(deleted)'
118         * or "#prelink#" if the executable has been deleted or the link changed. This
119         * function cleans this out and returns the clean path.
120         * @return
121         */
122        public String getNiceExecutablePath(){
123          this.setNiceExecutablePath();
124          return this.niceExecutablePath;
125        }
126            
127        private void setExecutablePath(){
128          String newPath = "";
129          
130          try{
131            newPath = proc.getExeFile().getSysRootedPath();
132                            
133          }catch (Exception e) {
134            try {
135              if (proc.getCmdLine().length > 0)
136                newPath = proc.getCmdLine()[0];
137              else
138                newPath = PATH_NOT_FOUND;
139                                            
140            } catch (Exception e2) {
141              newPath = PATH_NOT_FOUND;
142              return;
143            }
144          }
145          
146          if(!newPath.equals(this.executablePath)){
147            this.executablePath = newPath;
148            this.executablePathChanged.notifyObservers(this);
149          }
150        }
151            
152        /**
153         * Returns wether this user owns this process or not.
154         * 
155         * - Checks uid and * gid.
156         * - Checks if the given process is this frysk process if so returns false.
157         * - Also checks that the user has acces to /pro/exe if not false is returned.
158         * - Checks if this process is the init process, return false if so.
159         * 
160         * @return boolean; true of the user owns this process, and can debug it
161         *         false otherwise;
162         */
163        public boolean isOwned() {
164            if (this.getProc().getPid() == 1) {
165                return false;
166            }
167    
168            if (this.proc.getPid() == Manager.host.getSelf().getPid()) {
169                return false;
170            }
171    
172            if (Manager.host.getSelf().getUID() == 0) {
173                return true;
174            }
175    
176            try {
177                proc.getExeFile().getSysRootedPath();
178            } catch (Exception e) {
179                return false;
180            }
181    
182            if ((this.proc.getUID() == Manager.host.getSelf().getUID() || this.proc.getGID() == Manager.host.getSelf().getGID())) {
183                return true;
184            }
185    
186            return false;
187        }
188            
189            public String getFullExecutablePath(){
190              this.setExecutablePath();
191              return this.executablePath;
192            }
193            
194            /**
195             * Tries to call getExe() on the proc. If that 
196             * fails, then getCmmd[0] is used.
197             */
198            public String getExecutableName(){
199              this.setNiceExecutablePath();
200              return this.executableName;
201            }
202            
203            
204            public static class GuiProcFactory{
205                    static HashMap map = new HashMap();
206                    
207                    public static GuiProc getGuiProc(Proc proc){
208                            GuiProc guiProc;
209                            
210                            guiProc = (GuiProc)map.get(proc);
211                            
212                            if(guiProc == null){
213                                    guiProc = new GuiProc(proc);
214                                    map.put(proc, guiProc);
215                            }
216                            
217                            return guiProc;
218                    }
219            }
220            
221    }