Autorisierung für serielle Schnittstellen - Bitte um Test

In dieser Linux-Ecke dürfen nur Themen rund um Linux geschrieben werden.
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Autorisierung für serielle Schnittstellen - Bitte um Test

Beitrag von Omi »

Hallo und sorry für das etwas umfangreichere Posting!

Ich hätte die Bitte, folgende Routine mal auf Eurem Heimsystem zu testen und Rückmeldung zu geben.
Voraussetzung: Linux, einen Rechner mit seriellen Schnittstellen und Interesse am Thema.

Beim Wechsel von Windows auf Linux fiel schnell auf, dass die seriellen Schnittstellen nicht so einfach ansprechbar waren. Der angemeldete User muss die Rechte auf die Dateien haben oder (besser) in einer Gruppe mit entsprechenden Rechten sein.
D.h. ohne Rumdoktern im Terminal kein Zugriff. Beim Stöbern nach funktionierendem PB-Code bin ich zwar auf einige Nachfragen, jedoch bisher nicht auf so ganz befriedigende Antworten gestoßen.

Da mein bisher aufwändigstes Windowsprogramm ein Tool für die serielle Schnittstelle ist, wäre es mein Ziel gewesen, es ansatzweise so komfortable auf Linux umsetzen zu können.
Die professionelle Lösung ist, als Root eine Gruppe mit den Rechten an der Schnittstelle anzulegen und den User zur Gruppe hinzuzufügen.
Für den schnellen Heimbetrieb hab ich mir nach und nach folgendes erarbeitet und hätte gerne gewusst, ob dies in den meisten Umgebungen erfolgreich sein könnte:

Was sollte die aufgeführte Routine erledigen:
- Es listet vorhandene serielle Schnittstellen per debug (ttyS0, ...)
- Es listet die Rechte des aktuellen Users an diesen Ports per debug.
- Es bietet die Möglichkeit in einem automatisch erscheinenden Terminal die Rechte für jeden vorhandenen Port per 'sudo' für diese Sitzung auf den aktuellen User zu erweitern (sudo-Passwort nötig)
- Es zeigt die neuen Rechte an diesen Ports und per debug an.

Man muss die Programmumgebung dazu nicht verlassen, z.B. um nach Anweisung zwischendurch im Terminal arbeiten. Das Terminal wird automatisch nur zur Eingabe des sudo-Passwortes angeboten!

Dann sollte auch das PureBasic-Beispiel in .../examples/sources/SerialPort.pb laufen.
Leider Ist das Programm relativ umfangreich und abschreckend...

Code: Alles auswählen

;SERIAL_AUTORISATION ...

Global.i gComPortsNum, gAllAccess
Global.s gttyFile = GetHomeDirectory()+"tty.txt"
Global.s gComPortNumList

Structure ComPortData
	ComPortName.s
	ComPortAccessPre.b
	ComPortAccessPost.b
EndStructure

Global NewList ttyFileContent.ComPortData()

Procedure ComPortsExists(List ComList.ComPortData());                      Lists existing ComPorts
	Protected.i I, Pos, Line_, Num
	Protected.s ComPort, TempS
	If ReadFile(0, gttyFile)
		While Not Eof(0)
			Line_+ 1
			TempS= ReadString(0)
			If FindString(TempS, "at I/O")
				Pos= FindString(TempS, "ttyS")
				If Pos
					ComPort= "ttyS"
					Num+ 1
					I= 0
					While Mid(TempS, Pos + 4 + I, 1)<> " "
						ComPort+ Mid(TempS, Pos + 4 + I, 1)
						I+ 1
					Wend
					AddElement(ComList())
					ComList()\ComPortName= ComPort
				EndIf
			EndIf
		Wend
	EndIf
	ProcedureReturn Num
EndProcedure

Procedure.s ComPortNumList(List ComList.ComPortData());                   Built a list in string, f.e. '[01]', works only with single figure, 0 - 9
	Protected.s PortList= "["
	ResetList(ComList())
	While NextElement(ComList())
		PortList+ Mid(ComList()\ComPortName, FindString(ComList()\ComPortName, "ttyS") + 4)
	Wend
	PortList+ "]"
	ProcedureReturn PortList
EndProcedure

Procedure ComPortAccessbility(PostRights, List ComList.ComPortData());    Reads autorisation for existing ComPorts of current user
	Protected.i Line_, AllAccess= #True
	Protected.s TempS

	If ReadFile(0, gttyFile)
		While Not Eof(0)
			Line_+ 1
			TempS= ReadString(0)
			ResetList(ttyFileContent())
			If ListSize(ttyFileContent())
				If NextElement(ttyFileContent())
					Repeat
						If FindString(TempS, ttyFileContent()\ComPortName)
							If Mid(TempS, 8, 2)<> "rw";                                 No access for current user?
								If PostRights
									ttyFileContent()\ComPortAccessPost= #False
								Else
									ttyFileContent()\ComPortAccessPre= #False
									AllAccess= #False
								EndIf
							Else
								If PostRights
									ttyFileContent()\ComPortAccessPost= #True
								Else
									ttyFileContent()\ComPortAccessPre= #True
								EndIf
							EndIf
						EndIf
					Until NextElement(ttyFileContent())= 0
				EndIf
			EndIf
		Wend
	EndIf
	ProcedureReturn AllAccess
EndProcedure

;1. control kernel ringbuffer, find lines with 'ttyS', export to ttyFile ...
ProgramID = RunProgram("xterm", "-e " + #DQUOTE$ + "dmesg | grep ttyS | /usr/bin/tee " + gttyFile + #DQUOTE$, GetCurrentDirectory(), #PB_Program_Wait)
	
	Delay(100)
	gComPortsNum= ComPortsExists(ttyFileContent())
	Debug "Existing Com-Ports: " + Str(gComPortsNum)
	If gComPortsNum= 0: End : EndIf
	ResetList(ttyFileContent())
	While NextElement(ttyFileContent())
		Debug ttyFileContent()\ComPortName
	Wend
	gComPortNumList= ComPortNumList(ttyFileContent())
	
;2. list  files with 'ttyS'+no. of existing ports in 'gttyFile' ...
ProgramID = RunProgram("xterm", "-e " + #DQUOTE$ + "ls -l /dev/ttyS" + gComPortNumList + " | tee " + gttyFile + #DQUOTE$, GetCurrentDirectory(), #PB_Program_Wait)

	Delay(100)
	gAllAccess= ComPortAccessbility(0, ttyFileContent())
	Debug "Authorisation ..."
	ResetList(ttyFileContent())
	While NextElement(ttyFileContent())
		Debug ttyFileContent()\ComPortName + ": " + Str(ttyFileContent()\ComPortAccessPre)
		If ttyFileContent()\ComPortAccessPre= #False
			Debug "Loggin as 'sudo' to change authorisation for " + ttyFileContent()\ComPortName + " (close terminal if you want no change) ..."
			;3. Loggon as sudo and change autorisation for each port without accessiblity...
			ProgramID = RunProgram("xterm", "-e " + #DQUOTE$ + "sudo chmod a+rw /dev/" + ttyFileContent()\ComPortName + #DQUOTE$, GetCurrentDirectory(), #PB_Program_Wait)
		EndIf
	Wend
	
	If Not gAllAccess;                                                      Access on all ComPorts? - List with new rights on files ...
		ProgramID = RunProgram("xterm", "-e " + #DQUOTE$ + "ls -l /dev/ttyS" + gComPortNumList + " | tee " + gttyFile + #DQUOTE$, GetCurrentDirectory(), #PB_Program_Wait)
		
		Delay(100)
		ComPortAccessbility(1, ttyFileContent())
	  Debug "New authorisation ..."
		ResetList(ttyFileContent())
		While NextElement(ttyFileContent())
			Debug ttyFileContent()\ComPortName + ": " +  Str(ttyFileContent()\ComPortAccessPost)
		Wend
	EndIf
	
Unter Xubuntu 13.10, 32-Bit und Ubuntu 12.x, 64-Bit konnte ich die Routine bisher erfolgreich testen.
In einer VirtualBox müssen BEIM ANLEGEN bereits die Rechte an den Schnittstellen übergeben werden, sonst geht (auch nachträglich) nix!
Ziel des Ganzen wäre, für die meisten einigermaßen aktuellen Distributionen und Installationen eine funktionierende Routine zu schaffen.

Erstmal vielen Dank an die Mitwirkenden

Charly

PS:
Rücksetzen kann man die Rechte für Wiederholungen der Tests für jeden Port im Terminal mit:
sudo chmod a-rw /dev/ttySx (für x die Nummern des jeweilgen Ports angeben und erneut aufrufen, z.B. sudo chmod a-rw /dev/ttyS0, sudo chmod a-rw /dev/ttyS1, ...)

Beim nächsten login sind die ursprünglichen Rechte grundsätzlich wieder hergestellt.
PureBasic Linux-API-Library: http://www.chabba.de
Benutzeravatar
pcfreak1201
Beiträge: 38
Registriert: 17.12.2011 13:01
Computerausstattung: Linux Mint 17.3 (Rosa) x64 | PB 5.42LTS x64 (Linux+Win)
Wohnort: Arnsberg

Re: Autorisierung für serielle Schnittstellen - Bitte um Tes

Beitrag von pcfreak1201 »

Läuft bei mir (PB 5.42LTS x64 auf Linux Mint 17.3 (Rosa) Cinnamon) problemlos:

Code: Alles auswählen

Existing Com-Ports: 1
ttyS0
Authorisation ...
ttyS0: 0
Loggin as 'sudo' to change authorisation for ttyS0 (close terminal if you want no change) ...
New authorisation ...
ttyS0: 1
Allerdings ist das Konsolenfenster winzig. Kann man dafür nicht auch eine API aufrufen,
die das "normale" erweiterte Rechte-Fenster aufruft (also das z.B. für ein Update aufploppt)?

Gruß,
Stefan
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Re: Autorisierung für serielle Schnittstellen - Bitte um Tes

Beitrag von Omi »

Hallo pcfreak,

danke für die Rückmeldung.
Kann man dafür nicht auch eine API aufrufen,
Tut der Code ja :wink:
Es wird alles, was man i.d.R. in einem Terminal für die gewünschten Schnittstellen per Hand konfiguriert in den Terminal-Emulator XTerm übergeben. Man hat nur noch das evtl. sudo-Passwort einzugeben. Läuft (in einer aufgemotzten Version, (USB-Adapter)) jetzt im übrigen innerhalb eines Programmes auf allen (über 10) getesteten (und "anständigen") Distributionen.

Das Konsolefenster ist nicht von PureBasic sondern XTerm. Dieses kannst Du per [Strg]+Rechtsklick ins Fenster konfigurieren. Weiteres gibts per Kombi mit Mittel- und Linksklicks.

Viele Grüße und guten (Wieder-) Einstieg.
Charly
PureBasic Linux-API-Library: http://www.chabba.de
Benutzeravatar
pcfreak1201
Beiträge: 38
Registriert: 17.12.2011 13:01
Computerausstattung: Linux Mint 17.3 (Rosa) x64 | PB 5.42LTS x64 (Linux+Win)
Wohnort: Arnsberg

Re: Autorisierung für serielle Schnittstellen - Bitte um Tes

Beitrag von pcfreak1201 »

Gut ich meinte natürlich eine GUI-API ;-)
Die XTerm-Oberfläche sieht immer noch so aus wie zu fvwm2-Zeiten,
und die Schriftgröße ist halt standardmäßig seehr klein.
LOL - welches sind denn dann unanständige Distributionen :lol:
Antworten