#!/usr/bin/python ''' Created on July 14, 2022 @author: Hovanes Egiyan ''' import fcntl, struct, subprocess, os, errno, shutil, sys, optparse lock = struct.pack('hhllhh', fcntl.F_WRLCK, 0 , 0 , 0 , 0 , 0) unlock = struct.pack('hhllhh', fcntl.F_UNLCK, 0 , 0 , 0 , 0 , 0) defaultDirName = "Default" def tryExistingWorkspaces(dirName) : """ Return a workspace name that already exists in direcotry dirName and is not locked. If such a workspaces does not exist, return None """ # print "Searching for avilable Firefox profiler in {0}".format(dirName) workSpaceList = [os.path.join(dirName, dI) for dI in os.listdir(dirName) if (os.path.isdir(os.path.join(dirName, dI)) and dI != defaultDirName) ] # print workSpaceList for workSpace in workSpaceList: lockFileName = os.path.join(workSpace, "lock") # print "Will try file <{0}>".format(lockFileName) testFile = None try: testFile = open(lockFileName, "w") fcntl.fcntl(testFile.fileno(), fcntl.F_SETLK, lock) fcntl.fcntl(testFile.fileno(), fcntl.F_SETLK, unlock) testFile.close() os.remove(lockFileName) except IOError: if testFile != None: testFile.close() continue # print "Found unlocked workspace {0}, launching browser".format(workSpace) return workSpace print "No available workspaces found in {0}".format(dirName) return None def getWorkSpaceDirName( dirName, wsNumber ) : """ Get the directory name for a new workspace in a directory dirName and with number wsNumber """ # print "Directory is {0} , number is {1}".format( dirName, wsNumber ) wsName = "Profile_{0:06d}".format(wsNumber) return os.path.join(dirName, wsName) def createWorkSpace(dirName): wsDirName = None # Name of the template workspace that never gets used but keeps getting copied templateWorkspaceDirName = os.path.join( dirName, defaultDirName ) if( not os.path.exists(templateWorkspaceDirName) ): print "Template profile directory <{0}> does not exist".format(templateWorkspaceDirName) raise errno.ENOENT # File where we keep the last workspace number numberFileName = os.path.join( dirName, ".profile_number") # print "Reading file number from <{0}>".format(numberFileName) try: # Open the file with the WS number numberFile = open(numberFileName, "r") firstLine = numberFile.next() # print firstLine wsNumber = int(firstLine.split()[0]) + 1 # print "Number is {0}".format(wsNumber) wsDirName = getWorkSpaceDirName( dirName, wsNumber ) if( os.path.exists( wsDirName ) ) : print "Profile directory <{0}> already exists".format(wsDirName) raise OSError( "Profile <{0}> already exists".format(wsDirName) ) # Try to copy the default workspace into the new directory with the name found above try: shutil.copytree( templateWorkspaceDirName, wsDirName ) # Directories are the same except shutil.Error as e: print('Directory not copied. Error: %s' % e) # Any error saying that the directory doesn't exist except OSError as e: print('Directory not copied. Error: %s' % e) # Close the number with the lst workspace number and then reopen it to save the current number numberFile.close() numberFile = open(numberFileName, "w") numberFile.write( str(wsNumber) ) numberFile.write( "\n" ) numberFile.close() except IOError as err: print "Could not open file <{0}>".format(numberFileName) raise err return wsDirName if __name__ == '__main__': workspaceToUse = None existingWorkspace = None homeDir = os.environ['HOME'] chromiumMap = { "exec" : "chromium-browser", "prof_dir" : "/Chromium-Profiles-AUTO", "prof_opt" : "--user-data-dir=", # Equal sign at the end is important "default_opt" : ["--new-window", "-password-store=basic"] } firefoxMap = { "exec" : "firefox", "prof_dir" : "/Firefox-Profiles-AUTO", "prof_opt" : "--profile ", # Space at the end is important "default_opt" : ["--new-instance", "--no-remote"] } browserMap = { "chromium" : chromiumMap, "firefox" : firefoxMap } defaultBrowserName = "firefox" # defaultBrowserName = "chromium" # Define the command line parser and the potential options parser = optparse.OptionParser(usage = "usage: %prog [options] ") parser.add_option( "-n", "--new", action="store_true", dest="create_new", metavar="NEW_WS", default=True, help="Create new profile" ) parser.add_option( "-f", "--find", action="store_false", dest="create_new", metavar="NEW_WS", default=True, help="Try to find unused profile or create new profile" ) parser.add_option( "-b", "--browser", action="store", dest="browser_name", type="string", metavar="BROWSER_NAME", default=defaultBrowserName, help="Browser name" ) parser.add_option( "-o", "--opt", action="store", dest="browser_opt", type="string", metavar="BROWSER_OPT", default=None, help="Extra options for browser" ) parser.add_option( "-u", "--url", action="store", dest="browser_url", type="string", metavar="PAGE_URL", default="file:///usr/share/doc/HTML/en-US/index.html", help="URL to open" ) # Parse rgumants (opts, args) = parser.parse_args( sys.argv[1:] ) browserName = opts.browser_name browserOptList = opts.browser_opt browserUrl = opts.browser_url if browserName not in browserMap.keys() : print "This script is not set up for browser called {0}".format(browserName) print "Currently supported browsers are:\t", for brName in browserMap.keys(): print brName + "\t", print exit(-1) if( browserOptList == None ) : browserOptList = browserMap[browserName]["default_opt"] workspaceLocation = homeDir + browserMap[browserName]["prof_dir"] browserExecutable = browserMap[browserName]["exec"] # Try to see if there are unlock workspaces in the directory if ( not opts.create_new ): existingWorkspace = tryExistingWorkspaces(workspaceLocation) # print "Result is " , existingWorkspace # If no unlocked workspace found create a new workspace if(existingWorkspace == None): newWorkSpace = createWorkSpace(workspaceLocation) if(newWorkSpace != None): workspaceToUse = newWorkSpace else : workspaceToUse = None else : workspaceToUse = existingWorkspace browserDirFlag = browserMap[browserName]["prof_opt"] + workspaceToUse browserDirFlagList = browserDirFlag.split(" ") print "Will use " , workspaceToUse fakeCommand = ["ls" , "-l", workspaceToUse] # subprocess.call( fakeCommand ) if workspaceToUse != None: browserCommand = [browserExecutable] + browserDirFlagList + browserOptList + [browserUrl] print "Will call {0}".format( browserCommand ) subprocess.call( browserCommand ) else : print "Could not determine what profile to use in {0}".format(workspaceLocation)