tag:www.stefanwienert.net,2008:/ubuntuUbuntu - Stefan Wienert's Blog2010-02-16T09:09:23ZEnkiStefan Wienertstwienert@gmail.comtag:www.stefanwienert.net,2008:Post/342010-02-16T08:09:00Z2010-02-16T09:09:23ZYakuake mit Startskripts versehen - Automatische Einrichtung der Arbeitsumgebung<p>Diejenigen von euch, die eine <span class="caps">KDE</span> Umgebung unter Linux verwenden, kennen vielleicht yakuake, ein Terminalprogramm mit etwas EyeCandy, welches bei Druck von F12 aus dem oberen Bildschirmrand herausfährt.<br />
Ich selbst nutze zwar Gnome, nehme aber als priorisiertes Terminalprogramm trotzdem yakuake, da ich finde, dass das Farbschema “Dunkle Pasteltöne” einfach gut aussieht, und man die Shell, egal auf welchem Virtuellem Desktop man sich befindet, nie aus den Augen verliert (F12 und sie ist wieder da).</p>
<p>Die Dokumentation der Skriptfähigkeit ist etwas dürftig, außer einem <a href="http://88.191.25.234/wordpress/2009/05/09/yakuake-launch-on-start/">Blogeintrag</a> habe ich nicht sehr viel gefunden. Das dort abgebildete Beispielshellskript hab ich bei mir nicht zum Laufen bekommen, darum hab ich ein Ruby Programm dafür geschrieben…. (Ehrlich gesagt, find ich Shell Skript hässlich, keine Parameterliste, hässliche Conditional-Syntax… ja wann kommt denn endlich eine Ruby Shell?? :D)</p>
<h3>kurze Einführung</h3>
<p>Ersteinmal muss yakuake laufen, vornehmlich in einem initialen Zustand.<br />
Das Ganze läuft über qbus und man ruft prinzipiell nur ein paar recht einfache Shellkommandos auf:</p>
<p>Ein Aufruf von</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">qdbus org.kde.yakuake /yakuake/sessions <tt>
</tt><tt>
</tt># und<tt>
</tt><tt>
</tt>qdbus org.kde.yakuake /yakuake/tabs <tt>
</tt></pre></td>
</tr></table>
<p>Gibt uns alle möglichen Kommandos auf. Hier meine Favoriten:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">qdbus org.kde.yakuake <span class="rx"><span class="dl">/</span><span class="k">yakuake</span><span class="dl">/</span><span class="mod">sessions</span></span> addSession<tt>
</tt>qdbus org.kde.yakuake <span class="rx"><span class="dl">/</span><span class="k">yakuake</span><span class="dl">/</span><span class="mod">sessions</span></span> addSessionTwoHorizontal<tt>
</tt>qdbus org.kde.yakuake <span class="rx"><span class="dl">/</span><span class="k">yakuake</span><span class="dl">/</span><span class="mod">sessions</span></span> addSessionTwoVertical<tt>
</tt><span class="c"># Macht ein neues Tab (mit zwei, horizontal/vertikal geteilten Sessions sprich Terminals)</span><tt>
</tt><tt>
</tt>qdbus org.kde.yakuake <span class="rx"><span class="dl">/</span><span class="k">yakuake</span><span class="dl">/</span></span>tabs setTabTitle <span class="gv">$tabid</span> <span class="s"><span class="dl">'</span><span class="k">name</span><span class="dl">'</span></span><tt>
</tt><span class="c"># Setzt den Tab auf ein neues Label</span><tt>
</tt><tt>
</tt>qdbus org.kde.yakuake <span class="rx"><span class="dl">/</span><span class="k">yakuake</span><span class="dl">/</span><span class="mod">sessions</span></span> runCommandInTerminal <span class="gv">$sessionid</span> <span class="s"><span class="dl">'</span><span class="k">command</span><span class="dl">'</span></span><tt>
</tt><span class="c"># Führt ein Shell-Kommando in Terminal Nr X aus</span><tt>
</tt><tt>
</tt>qdbus org.kde.yakuake | grep <span class="co">Sessions</span> | cut --fields <span class="s"><span class="dl">"</span><span class="k">3</span><span class="dl">"</span></span> --delim=<span class="s"><span class="dl">"</span><span class="k">/</span><span class="dl">"</span></span> | sort -n | tail -n <span class="i">1</span><tt>
</tt><span class="c"># Gibt uns die letzte vergebene SessionID aus</span><tt>
</tt><tt>
</tt></pre></td>
</tr></table>
<p>Wie man sieht, besteht das eigentliche Problem, den Überblick über die Sessions (Terminals) und Tabs zu behalten. Wenn man keine geteilten Fenstern nutzt, sollten die beiden identisch sein.</p>
<h3>Ein Ruby-Wrapper</h3>
<p>Um den IDs herr zu werden, habe ich das Ganze in ein Rubyprogramm, eine Klasse, geflochten:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt>35<tt>
</tt>36<tt>
</tt>37<tt>
</tt>38<tt>
</tt>39<tt>
</tt><strong>40</strong><tt>
</tt>41<tt>
</tt>42<tt>
</tt>43<tt>
</tt>44<tt>
</tt>45<tt>
</tt>46<tt>
</tt>47<tt>
</tt>48<tt>
</tt>49<tt>
</tt><strong>50</strong><tt>
</tt>51<tt>
</tt>52<tt>
</tt>53<tt>
</tt>54<tt>
</tt>55<tt>
</tt>56<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">class</span> <span class="cl">Yakuake</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">initialize</span><tt>
</tt> <span class="iv">@cid</span>=<span class="i">0</span> <tt>
</tt> <span class="iv">@tabid</span>=<span class="i">0</span> <tt>
</tt> <span class="r">end</span> <tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">exec</span>(cmd)<tt>
</tt> puts cmd <tt>
</tt> system cmd <tt>
</tt> <span class="r">end</span> <tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">add_splitted_tab</span>(title1,command1,command2)<tt>
</tt> exec <span class="s"><span class="dl">"</span><span class="k">qdbus org.kde.yakuake /yakuake/sessions addSessionTwoHorizontal</span><span class="dl">"</span></span><tt>
</tt> <span class="iv">@tabid</span>+=<span class="i">1</span> <tt>
</tt> cid = last <tt>
</tt> exec <span class="s"><span class="dl">"</span><span class="k">qdbus org.kde.yakuake /yakuake/tabs setTabTitle </span><span class="il"><span class="idl">#{</span><span class="iv">@tabid</span><span class="idl">}</span></span><span class="k"> '</span><span class="il"><span class="idl">#{</span>title1<span class="idl">}</span></span><span class="k">'</span><span class="dl">"</span></span><tt>
</tt> [command1, command2].each_with_index <span class="r">do</span> |command,index| <tt>
</tt> <span class="r">if</span> command <tt>
</tt> ccid = cid <span class="i">-1</span> + index <tt>
</tt> exec <span class="s"><span class="dl">"</span><span class="k">qdbus org.kde.yakuake /yakuake/sessions runCommandInTerminal </span><span class="il"><span class="idl">#{</span>ccid-<span class="i">1</span><span class="idl">}</span></span><span class="k"> '</span><span class="il"><span class="idl">#{</span>command<span class="idl">}</span></span><span class="k">'</span><span class="dl">"</span></span> <tt>
</tt> <span class="r">end</span> <tt>
</tt> <span class="r">end</span> <tt>
</tt> <span class="r">end</span> <tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">add_tab</span>(name, command=<span class="pc">false</span>)<tt>
</tt> exec <span class="s"><span class="dl">"</span><span class="k">qdbus org.kde.yakuake /yakuake/sessions addSession</span><span class="dl">"</span></span><tt>
</tt> <span class="iv">@tabid</span>+=<span class="i">1</span> <tt>
</tt> exec <span class="s"><span class="dl">"</span><span class="k">qdbus org.kde.yakuake /yakuake/tabs setTabTitle </span><span class="il"><span class="idl">#{</span><span class="iv">@tabid</span><span class="idl">}</span></span><span class="k"> '</span><span class="il"><span class="idl">#{</span>name<span class="idl">}</span></span><span class="k">'</span><span class="dl">"</span></span><tt>
</tt> <span class="r">if</span> command <span class="r">and</span> !command.empty? <tt>
</tt> exec <span class="s"><span class="dl">"</span><span class="k">qdbus org.kde.yakuake /yakuake/sessions runCommandInTerminal </span><span class="il"><span class="idl">#{</span>last - <span class="i">1</span><span class="idl">}</span></span><span class="k"> '</span><span class="il"><span class="idl">#{</span>command<span class="idl">}</span></span><span class="k">'</span><span class="dl">"</span></span> <tt>
</tt> <span class="r">end</span> <tt>
</tt> <span class="r">end</span> <tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">execute</span>(terminal_id, command)<tt>
</tt> exec <span class="s"><span class="dl">"</span><span class="k">qdbus org.kde.yakuake /yakuake/sessions runCommandInTerminal </span><span class="il"><span class="idl">#{</span>terminal_id<span class="idl">}</span></span><span class="k"> '</span><span class="il"><span class="idl">#{</span>command<span class="idl">}</span></span><span class="k">'</span><span class="dl">"</span></span> <tt>
</tt> <span class="r">end</span> <tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">last</span><tt>
</tt> <span class="sh"><span class="dl">`</span><span class="k">qdbus org.kde.yakuake | grep Sessions | cut --fields "3" --delim="/" | sort -n | tail -n 1</span><span class="dl">`</span></span>.strip.to_i <tt>
</tt> <span class="r">end</span> <tt>
</tt><span class="r">end</span> <tt>
</tt><tt>
</tt><span class="c"># Aufruf/Einrichtung des Workspace:</span><tt>
</tt>y=<span class="co">Yakuake</span>.new<tt>
</tt>y.add_splitted_tab(<span class="s"><span class="dl">"</span><span class="k">sshs</span><span class="dl">"</span></span>,<span class="s"><span class="dl">"</span><span class="k">ssh username@server.de</span><span class="dl">"</span></span>,<span class="s"><span class="dl">"</span><span class="k">ssh username@server2.de</span><span class="dl">"</span></span>)<tt>
</tt><span class="c"># jeweils in den Arbeitsordner navigieren und svn up</span><tt>
</tt>y.execute(y.last-<span class="i">2</span>,<span class="s"><span class="dl">"</span><span class="k">cd public_html/modules</span><span class="dl">"</span></span>)<tt>
</tt>y.execute(y.last-<span class="i">2</span>,<span class="s"><span class="dl">"</span><span class="k">svn up</span><span class="dl">"</span></span>)<tt>
</tt>y.execute(y.last-<span class="i">1</span>,<span class="s"><span class="dl">"</span><span class="k">cd ~username/public_html/modules</span><span class="dl">"</span></span>)<tt>
</tt>y.execute(y.last-<span class="i">1</span>,<span class="s"><span class="dl">"</span><span class="k">svn up</span><span class="dl">"</span></span>)<tt>
</tt><span class="c"># ein paar irbs zum "rumprobieren"</span><tt>
</tt>y.add_splitted_tab(<span class="s"><span class="dl">"</span><span class="k">Irbs</span><span class="dl">"</span></span>, <span class="s"><span class="dl">"</span><span class="k">irb</span><span class="dl">"</span></span>,<span class="s"><span class="dl">"</span><span class="k">irb</span><span class="dl">"</span></span>)<tt>
</tt><span class="c"># Ein Programmstarter</span><tt>
</tt>y.add_tab(<span class="s"><span class="dl">"</span><span class="k">Progs</span><span class="dl">"</span></span>,<span class="s"><span class="dl">"</span><span class="k">ruby ~zealot64/rubyqt/tray.rb&</span><span class="dl">"</span></span>)<tt>
</tt><tt>
</tt></pre></td>
</tr></table>
tag:www.stefanwienert.net,2008:Post/332010-02-08T11:06:00Z2010-02-08T12:06:13ZBessere PHP Shell, ähnlich wie Rubys irb<p>Nachdem ich bei Ruby von der recht mächtigen und gut tunebaren Interactive Ruby Shell (<a href="http://tagaholic.me/2009/03/13/hirb-irb-on-the-good-stuff.html"><span class="caps">HIRB</span></a> und <a href="http://www.rubyinside.com/wirble-tab-completion-and-syntax-coloring-for-irb-336.html">Wirble</a> seien hier anzumerken) verwöhnt wurde, war ich auf der Suche nach einer ähnlichen Lösung für <span class="caps">PHP</span>.<br />
Leider ist die eingebaute <span class="caps">CLI</span> Shell mit “php -a” relativ nutzlos, da man Output selbst ausgeben muss, es keine Autocomplete gibt usw.</p>
<p>Allerdings gibt es die <a href="http://jan.kneschke.de/projects/php-shell/">php-shell</a> welche recht interessant wirkt und ich heute mal runtergeladen habe.</p>
<p>Unter Ubuntu muss man noch php pear nachinstallieren:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">sudo apt-get install php-pear php5-cli php5-dev<tt>
</tt>sudo pear install http://jan.kneschke.de/assets/2007/2/17/PHP_Shell-0.3.1.tgz<tt>
</tt><tt>
</tt># Jetzt kann die shell mit:<tt>
</tt>php-shell.sh<tt>
</tt>#gestartet werden<tt>
</tt></pre></td>
</tr></table>
<p>Das reduziert den <span class="caps">PHP</span>-Schmerz schonmal ein ganzes Stück :)</p>tag:www.stefanwienert.net,2008:Post/112009-11-03T16:09:00Z2009-11-03T17:09:24ZATI-Graphik byebye... oder: Die Sache mit dem Lokalpatriotismus<p>Nun ist er für mich vorbei, der Leidensweg mit meiner <span class="caps">ATI</span> Grafikkarte. (Die direkte Konkurrenz ist recht ersichtlich, möchte aber keine [unbezahlte] Werbung machen).</p>
<p>Seit heute kann ich <strong>endlich</strong> Desktopeffekte anschalten <span class="caps">UND</span> ein Video schauen… ist das nicht unglaublich? – <strong>nicht wirklich</strong>. So ziemlich alles mögliche habe ich probiert, aber meine alte Graphikkarte lies sich nie dazu überreden,.. warum? Weil die Linuxunterstützung von <span class="caps">ATI</span>/<span class="caps">AMD</span> etwas… minimal ausfällt.</p>
<p>Da <span class="caps">AMD</span> ein <a href="http://fab36.amd.com/de-de/">großes Werk in Dresden, die FAB36</a> hat, habe ich bisher bei einer Auswahl meiner PC-Komponenten stets darauf geachtet, etwas aus diesem Hause zu kaufen, zu dem <a href="http://www.heise.de/newsticker/meldung/AMD-uebernimmt-ATI-fuer-5-4-Milliarden-Dollar-144435.html"><span class="caps">ATI</span> seit einiger Zeit gehört</a>. <br />
Nach meinem Komplettumstieg zu Linux (Ubuntu) vor knapp einem Jahr musste ich allerdings schmerzlich feststellen, dass, ganz im Gegensatz zu sämtlichen anderen Hardwarekomponenten, die <span class="caps">ATI</span>-Grafikkarten nicht, “Aus der Kiste” (Out-of-the-box) laufen, ganz im Gegenteil (Ganz unrepräsentative Aussage: hatte hierbei Erfahrungen mit 2 verschiedenen <span class="caps">ATI</span>-Grafikkarten).</p>
<h3>Der nicht ganz reibungslose Umstieg von <span class="caps">ATI</span> auf <span class="caps">NVIDIA</span></h3>
<p>Nach EInbau der Grafikkarte hat das <span class="caps">BIOS</span> ohne (größere) Probleme (Stichwort: Deaktivierung des internen Graphikchips) die nvidia erkannt. Nach <span class="caps">GRUB</span> und etwas Präambel allerdings…<br />
Rausschmiss in einem Busybox-ähnlichem Loginfenster, allerdings mit Geflacker, mit extremen Lag bei Tastatureingaben, welche u.a. die Eingabe des Passworts unmöglich gestalten.<br />
Mein Vorgehen danach war:</p>
<ul>
<li>Reboot, bei Grub “Recovery” des Kernels als Bootoption</li>
<li>drop to root shell</li>
</ul><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">dpkg-reconfigure -phigh xserver-xorg<tt>
</tt>sudo vim /etc/X11/xorg.conf<tt>
</tt></pre></td>
</tr></table>
<p>und dort erstmal alles löschen, was radeon/fglrx zu tun hatte (in meinem Fall war ich nach einiger Zeit beim freien “radeon” Treiber hängengeblieben). <br />
Danach habe ich mich mit links2 auf die Suche begeben :) und gemäß des <a href="http://wiki.ubuntuusers.de/Grafikkarten/Nvidia/nvidia">ubuntuusers-Beitrags zum nvidia-Treiber</a> das nvidia-Paket installiert:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">nvidia-glx-185<tt>
</tt></pre></td>
</tr></table>
<p>Nach einem Reboot war alles wieder normal :) (in meinem Fall kam ich sogar ohne einen Neustart aus, indem ich einfach “sudo gdm” ausgeführt hatte, nachdem der recovery-Modus normal weitergebootet und mich in einer tty rausgeschmissen hatte).</p>
<h3>Fazit:</h3>
<p>Ich möchte keineswegs <span class="caps">ATI</span> schlechtreden, allerdings hatte ich zumindest bei meinen beiden Graphikkarten alles andere als gute Erfahrungen, und auch in einigen Foren gelesen, dass die Linux-Unterstützung von <span class="caps">ATI</span> nicht weit her ist. Ich *hoffe jetzt wird alles besser…^^</p>tag:www.stefanwienert.net,2008:Post/92009-11-01T10:07:00Z2009-11-01T11:07:19ZProbleme beim Upgrade von Ubuntu Jaunty zu Karmic Koloa<p>Heute habe ich meinen Rechner angemacht, und siehe da: Kein Sound.</p>
<p>Meine Soundkarte wurde nicht gefunden, und auch ein Neustart und Reinstallation von pulseaudio brachte nichts.<br />
Weiterhin wird meine <span class="caps">ATI</span> HD3100 nicht unterstützt, und das Desktop ruckelt so vor sich hin, eine manuelle Installation des fglrx-Treibers von <span class="caps">ATI</span> bricht ab, da die XServer-Version noch nicht unterstützt wird….</p>
<p>Doch dann beim Booten, viel mir auf, dass nicht die Kernelversion 2.6.31-14 sondern 2.6.28 gebootet wird, obwohl ja die 31 Teil des neuen Ubuntus sein sollte.<br />
Also:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">sudo update grub<tt>
</tt></pre></td>
</tr></table>
<p>Durchklickern und neustart…. und beides funktioniert wieder :)</p>
<p>Da wurde wohl vergessen die Kernelversion beim Updatemanager mit einzubeziehen..? Wenn man mal danach <a href="http://forum.ubuntuusers.de/topic/kein-sound-nach-upgrade-auf-karmic-64bit/">googlet</a>, stellt man fest, dass es noch einige andere mit diesem Problem gibt.</p>
<p>Im Nachhinein würde ich persönlich ein Upgrade von Jaunty zu Karmic machen; Probleme beim Update hatte ich schon beim letzten mal von Intrepid zu Jaunty. Die Updatefunktion scheint mir demnach noch etwas buggy, allerdings ist eine Neuinstallation erfahrungsgemäß relativ problemfrei.</p>
<p>Zusammenfassend mal mein (Negativ)-Fazit:</p>
<ul>
<li>Empathy anstelle Pidgin… <span class="caps">WTF</span>? Ok, Empa unterstützt Voicechat, aber hässlich, und bei mir etwas langsam. <a href="http://de.wikipedia.org/wiki/Off-the-Record_Messaging"><span class="caps">OTR</span>-Plugin</a> auch noch nicht vorhanden (damit <span class="caps">ICQ</span>/<span class="caps">MSN</span>/QQ-Chats aufgrund der AGBs nutzlos^^)</li>
<li>Siehe letzten Post: Gedit hat neue <span class="caps">API</span>-Daten für die Snippets</li>
<li>Grafikprobleme mit <span class="caps">ATI</span> (altes Thema), allerdings durch das Kernelupdate soweit behoben</li>
<li>Die anderen Features bringen mir relativ wenig (Ubuntu One Integration…)</li>
<li>Mal schauen, ob mein Soundbug, welcher nach einer längeren Zeit Videoguckens auftritt und sich durch einen 1-2minütigen Lag im Sound + Bild äußert, behoben ist…</li>
</ul>
<p>Nichtsdestotrotz bleibt es ein Ubuntu, und damit immer noch eines der bedienerfreundlichsten und am meisten Community-unterstützten Linux Distributionen überhaupt.</p>