Il existe une commande DSPSAVF qui permet de visualiser le contenu d’un Save File (SAVF), elle est très utile et nous nous sommes demandés si nous pouvions améliorer son ergonomie. Depuis l’intégration des Technical Release 7.5 TR2 et 7.4 TR8, de nouvelles vues et tables de fonctions permettent d’obtenir des informations à propos des SAVF […]
Contrôler le nombre de paramètres passés à un programme CL – %PARMS() / CEETSTA
Il arrive parfois d’avoir moins de paramètres passés à un programme CL que le nombre attendu, par exemple si on ajoute un paramètre à ce dernier mais que pour diverses raisons on ne souhaite pas modifier et recompiler tous les programmes qui y font appel.
Il existe deux solutions relativement simples à implémenter pour contrôler le nombre de paramètres transmis afin d’adapter en conséquence le comportement du programme : La fonction intégrée %PARMS et l’API CEETSTA.
%PARMS() – V7R4 et ultérieures
À partir de la V7R4, rien de plus simple, il suffit d’utiliser la fonction intégrée %PARMS(), qui retourne le nombre de paramètres :
PGM PARM(&PARAM1 &PARAM2)
/* Paramètres */
DCL VAR(&PARAM1) TYPE(*CHAR) LEN(10)
DCL VAR(&PARAM2) TYPE(*CHAR) LEN(10)
/* Corps du programme en fonction du passage du paramètre */
IF COND(%PARMS() *EQ 2) THEN(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 est renseigné')
ENDDO
ELSE CMD(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 n''est pas renseigné')
ENDDO
ENDPGM
Malheureusement, si on est confrontés à une contrainte de version, %PARMS ne descend pas en dessous de la V7R4 :

CEETSTA – V7R3 et antérieures
Dans ce cas, la solution la plus propre (je ne parlerai donc pas de monitoring sur un CHGVAR) est l’utilisation de l’API CEETSTA.
Il suffit de lui passer en paramètre :
– Une variable qui contiendra la valeur de retour, 1 si le paramètre est transmis, 0 s’il n’est pas transmis
– Une variable indiquant la position du paramètre à contrôler
| presence_flag | Sortie | *INT | Variable de retour : 1 ou 0 |
| arg_num | Entrée | *INT | Position de la variable à tester |
PGM PARM(&PARAM1 &PARAM2)
/* Paramètres */
DCL VAR(&PARAM1) TYPE(*CHAR) LEN(10)
DCL VAR(&PARAM2) TYPE(*CHAR) LEN(10)
/* Déclaration des variables nécessaires à l'utilisation de l'API */
DCL VAR(&PRESENCE) TYPE(*INT) /* Variable de retour : 1 ou 0 */
DCL VAR(&ARG_NUM) TYPE(*INT) VALUE(2) /* Position de la variable à tester */
/* Appel de l'API */
CALLPRC PRC('CEETSTA') PARM((&PRESENCE) (&ARG_NUM))
/* Corps du programme en fonction du passage du paramètre */
IF COND(&PRESENCE *EQ 1) THEN(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 est renseigné')
ENDDO
ELSE CMD(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 n''est pas renseigné')
ENDDO
ENDPGM
Remarques
Le compte des paramètres pour la arg_num commence à 1
La valeur de retour est un *INT pas un *LGL
Pour plus de détails
Documentation IBM – %PARMS() : https://www.ibm.com/docs/en/i/7.5?topic=procedure-parms-built-in-function
Documentation IBM – CEETSTA : https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_75/apis/CEETSTA.htm
Vous utilisez RDI pour éditer vos programmes RPGLE et vous avez des cartes de déclaratives
H,D,F et vous voulez les convertir en free , voici 2 solutions simples
Solution 1, en ligne sur notre site
https://www.volubis.fr/convertisseur.html
Collez votre sélection dans le formulaire et appuyer sur le bouton Convert

Il vous faudra recopier votre sélection.
Solution 2, installez un plugin Eclipse
Craig Rutledge en a créé un bien il est disponible ici
https://jcrcmds.sourceforge.net/eclipse/rdi8.0/
Suivez la procédure pour paramétrer le plugin dans RDI et l’installation de la bibliothèque JCRCMDS s’il elle n’existe pas sur votre partition, c’est la commande JCRHDF qui sera utilisée, vous pouvez également l’utiliser en 5250, si vous le désirez
L’utilisation est très simple dans un source de type RPGLE ou SQLRPGLE , vous avez une nouvelle option sur le clic droit, JCRCMDS.
.
.
.
Voila , simple et efficace
Se connecter à un serveur SSH exécuté sous Windows à partir d’un IBM i (Comment obtenir la log pour débuguer les problèmes éventuels)

Mise en place d’OpenSSH Server sur Windows
Pour mettre en place OpenSSH Server sur Windows, la méthode « standard » consiste à passer par les Paramètres > Applications et fonctionnalités > fonctionnalités facultatives :


Il est recommandé de redémarrer Windows une fois la fonctionnalité ajoutée.
Il suffit ensuite de démarrer le serveur via le gestionnaire de Services Windows :

Il est également souhaitable de configurer le démarrage automatique du serveur :

Remarque
Il est également possible d’installer OpenSSH sur Windows via d’autres sources (GitHub par exemple) ce qui permet, entre autres, de choisir plus facilement sa version d’OpenSSH, voir section Détail.
Création d’un jeu de clefs SSH via ssh-keygen
Pour plus de détails sur la création de clefs, vous pouvez vous référer à l’article de Guillaume Gestion des clefs SSH.
Il est également possible d’utiliser PuttyGen, outil venant avec le client Putty pour générer le jeu de clefs de manière graphique (https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html).
Dans cet article je vais tout réaliser sur l’IBM i via QSH :
$ ssh-keygen -t ecdsa -f ~/.ssh/ssh_key
Mise en place de la clef privée et configuration côté IBM i (client)
On a généré la clef privée dans le répertoire .ssh de l’utilisateur, donc elle est déjà bien en place. Il suffit donc de créer un fichier config dans le répertoire .ssh de l’utilisateur afin de simplifier nos commandes pour la suite.
Voici un exemple de fichier config :
[~/.ssh/config]
Host windows
Hostname sshd_server.lan
User jl
IdentityFile ~/.ssh/key
StrictHostKeyChecking accept-new
| Host | Nom de la configuration, utilisé à la place des différentes informations à la connexion |
| Hostname | Adresse ou nom du serveur à atteindre |
| User | Nom de l’utilisateur |
| IdentityFile | Chemin vers la clef privée |
| StrictHostKeyChecking accept-new | Permet d’ajouter automatiquement la signature du serveur distant au known_hosts |
Mise en place de la clef privée et configuration côté Windows (serveur)
Il faut transférer la clef ssh_key.pub vers Windows et l’ajouter soit au fichier %UserProfile%.ssh\authorized_keys pour un utilisateur lambda, soit au fichier C:\ProgramData\ssh\administrators_authorized_keys pour un utilisateur ayant des droits d’administrateur local.
Attention à ce niveau, les droits des fichiers sont un peu particulières, il faut comme toujours avec le SSH réduire au maximum les utilisateurs ayant accès au fichier et, particularité de Windows, ajouter le droit de lecture au profil de service local Système :

Activation du fichier de log – Configuration sshd_config
Afin de pouvoir analyser d’éventuels problèmes ou simplement vouloir observer un peu plus en détail les différentes étapes de la mise en relation d’un flux ssh il est possible d’activer la log du serveur.
Par défaut celle-ci est redirigée vers les journaux d’évènements Windows et est seulement en « info ».
On les retrouver via l’Observateur d’événements Windows :

Le mieux à mon avis est de repasser par un système plus standard, soit un vrai fichier de logs.
Pour ce faire, il faut aller modifier le fichier de configuration du serveur SSH, généralement il se trouve ici :
C:\ProgramData\ssh\sshd_config
ou
%ProgramData%\ssh\sshd_config
Il faut rechercher les lignes suivantes :
[sshd_config]
# Logging
#SyslogFacility AUTH
#LogLevel INFO
Les décommenter et indiquer les valeurs suivantes :
[sshd_config]
# Logging
SyslogFacility LOCAL0
LogLevel Debug3
Une fois la configuration modifiée et le serveur redémarré, il suffit de retenter une connexion puis d’aller consulter le fichier de log :
C:\ProgramData\ssh\logs\sshd.log
ou
%ProgramData%\ssh\logs\sshd.log
Remarque
Les problèmes courants se passent généralement autour des lignes liées au fichier authorized_keys ou administrators_authorized_keys, problèmes de droits ou
chemin du fichier utilisé…
Test de SSH IBM i vers Windows
On peut maintenant tester le tout via QSH ou CALL QP2TERM.
Grâce au fichier config la commande est simple :
(l’option -T permet de désactiver l’allocation d’un pseudo terminal)
$ ssh -T windows
Microsoft Windows [version 10.0.19045.3208]
(c) Microsoft Corporation. Tous droits r
Il est maintenant possible d’exécuter des commandes Shell Windows à partir de cette connexion.
Si on voulait obtenir les mêmes niveaux de log côté client (IBM i) que l’on a activé côté Windows, on pourrait utiliser la commande suivante :
$ ssh -T -vvv windows
OpenSSH_8.0p1, OpenSSL 1.1.1t 7 Feb 2023
debug1: Reading configuration data /home/jl/.ssh/config
debug1: /home/jl/.ssh/config line 1: Applying options for *
debug1: /home/jl/.ssh/config line 4: Applying options for laptop
debug1: Reading configuration data /QOpenSys/QIBM/ProdData/SC1/OpenSSH/etc/ssh_config
...
Microsoft Windows [version 10.0.19045.3208]
(c) Microsoft Corporation. Tous droits r
Pour plus de détails
OpenSSH.com : https://www.openssh.com/
OpenSSH Server sous Windows – Document Microsoft : https://learn.microsoft.com/fr-fr/windows-server/administration/openssh/openssh_overview
OpenSSH – GitHub : https://github.com/PowerShell/Win32-OpenSSH/releases
Dans la dernière TR est apparue une nouveauté très intéressante « API RSE », c’est un ensemble d’API REST fournies avec votre système d’exploitation au travers du serveur ADMIN5.
![]()
Ces APIs sont utilisables depuis le web et permettent de lancer des commandes, accéder à l’IFS, de lancer de requêtes SQL…
Ce service ne fonctionne qu’en TLS vous devrez donc le sécuriser par l’administration http ://Votre_systeme:2001/HTTPAdmin

Vous devez ensuite le démarrer s’il ne l’est pas c’est le serveur ADMIN5
==>STRTCPSVR SERVER(*IAS) INSTANCE(admin5)
Ce serveur tourne par défaut sur le port 2012
https://Votre_systeme:2012/openapi/ui/

Vous devrez vous authentifiez pour commencer utilisez un user et un mot de passe ibmi, vous cliquez sur authorize 
Nous allons tester une commnde CL

Vous cliquez sur try input
Vous avez un flux json avec vos commandes IBMI à l’intérieur vous cliquez sur execute
Vous avez alors le résultat


A noter que vous avez le lien, en haut pour l’intégrer dans vos applications
Conclusion
C’est gratuit c’est technologies actuelles, testez les possibilités de ce service
Pour en savoir plus
la pause café de volubis ici : https://www.volubis.fr/Pausecaf/PAUSECAF91.html
le site IBM : https://www.ibm.com/support/pages/node/6982701
Nous utilisons de plus en plus de certificats pour crypter nos communications. Leur gestion via DCM sur l’IBM i devient donc de plus en plus nécessaire et « subtile ».
Les outils standards
Interface web de DCM (Digital Certificate Manager)
Accès par http://partition:2001/dcm
Beaucoup plus pratique et réactive depuis sa réécriture, elle comprend l’ensemble des fonctions (presque en réalité) : création des autorités, création des certificats, gestion des applications (au sens DCM), affectation, renouvellement, importation et exportation :

C’est propre, pratique.
Pour rappel, le principe : DCM permet de gérer les certificats (stocker, renouveler etc …), mais également de les affecter à une ou plusieurs applications IBM i. La notion d’application dans DCM est proche d’une notion de service : serveur telnet, serveur http, serveur ou client FTP et bien d’autres.
Ainsi un certificat peut être assigné à aucune, une ou plusieurs applications :

Et chaque application dispose de ses propres attributs, permettant par exemple de choisir les niveaux de protocoles :

A priori, on a pas de raison d’aller modifier ces attributs très souvent, l’interface web est parfaite pour ces actions
Services SQL
Pour plus de facilité, et de capacité d’automatisation, IBM délivre une fonction table (UTDF) : qsys2.certificate_info
Documentation : https://www.ibm.com/docs/en/i/7.5?topic=services-certificate-info-table-function
Disponible avec IBM i 7.5, 7.4 avec SF99704 niveau 13 et 7.3 avec SF99703 niveau 24
Exemple (IBM) :

Très utile pour obtenir directement toutes les informations, les dates de péremption etc …
Si vous êtes dans des niveaux incompatibles (ce ne devrait plus être le cas), nous avions fait pour vous une commande équivalente basée sur les APIs : https://github.com/FrenchIBMi/Outils/tree/master/API%20securite

DCM-tools
Grâce à Jesse Gorzinski (M. Open Source chez IBM), vous disposez également de commandes shell pour effectuer les principales actions de DCM : création, affectation de certificats, liste …
Voir le produit et l’installation ici : https://github.com/ThePrez/DCM-tools
Il faut absolument l’installer, cela vous permet d’automatiser de nombreuses actions courantes.
Exemple :

Les applications ?
« Houston, nous avons un problème ! ». Pas si grave non plus …
Il est facile de déterminer quels sont les certificats expirés ou qui vont expirer. Donc ceux à renouveler (création par DM ou importation). Par contre, seul l’interface web de DCM permet de voir les applications assignées, et donc les impacts de la péremption du certificat !
La connaissance des applications est primordiale : certaines nécessitent un arrêt/redémarrage du service (donc une interruption pour les utilisateurs), d’autres non.
Si aucune application n’est liée, on ne va peut être rien faire. Sinon, on va anticiper (sisi).
DCM permet de voir les applications, mais il vous faut aller sur le certificat et voir le détail par l’interface graphique. Donc humainement sur chacune de vos partitions.
API -> fonction table (UDTF)
Cette information est accessible par les APIs de DCM.
Pour plus de faciliter, nous vous proposons une fonction table SQL : listedcmapplication
Disponible en open source ici : https://github.com/FrenchIBMi/Outils/tree/master/dcm
L’objectif est de lister les applications ET les certificats associés :

Les deux paramètres permettent de sélectionner les applications avec ou sans certificat, les applications serveur ou client.
Vous pouvez également facilement utiliser les informations conjointes de qsys2.certificate_info. Par exemple, quels certificats vont expirer dans le mois et quelles sont les applications impactées :

Le code est open source, il est perfectible, n’hésitez pas à participer !
Quelques idées : agrégation des informations de différentes partitions, service correspondant actif ou non …
Ce son des fichiers qui ont l’extension MD, ce format a été créer par John Gruber, son but était de produire des fichiers formatés très simple à administrer un peu comme RTF mais encore en plus simple.
Ce format a été adopté dans le monde open source comme un standard, par exemple les gens qui publient sur Github, mettrons un readme.md pour décrire leurs publications.
https://gist.github.com/JulienRAVIA/1cc6589cbf880d380a5bb574baa38811
La syntaxe est très simple vous pouvez l’apprendre ici :
https://blindhelp.github.io/recapitulatifsyntaxemarkdown.html

Par exemple, pour mettre des titres vous devrez utiliser le caractère #

Si la syntaxe est relativement simple, nous vous conseillons d’utiliser un éditeur pour commencer
Celui que nous utilisons s’appelle JOPLIN (Merci à Yvon qui nous l’a fait découvrir)
Vous pouvez le télécharger là https://joplinapp.org/
(il existe sous forme d’extension pour VSE également, et même sur téléphone)
L’utilisation est très simple, et relativement classique pour les utilisateurs de produits Windows
Vous avez une barre avec les différents éléments que vous voulez intégrer.

L’outil est WYSIWYG ce qui permet de voir en temps réel ce que vous voulez faire

il dispose également de nombreuses possibilités d’exportation comme HTML et PDF
Conclusion :
C’est un format simple à utiliser et c’est un standard pour les nouveaux qui arrivent sur notre plateforme.
il est donc fortement conseillé de vous y mettre, et l’effort n’est pas important au regard de ce qu’il peut rapidement vous apporter.
Vous pourrez facilement faire des docs techniques de qualité et les exporter, il existe de nombreuses extensions pour vous aider
Sites à connaitre
https://fr.wikipedia.org/wiki/Markdown
https://www.markdownguide.org/basic-syntax/
https://www.ionos.fr/digitalguide/sites-internet/developpement-web/markdown/ (en français)
Nous utilisons de plus en plus les services SQL pour de nombreuses actions : accès aux *DTAQ, *DTAARA, travaux etc …
Par exemple, pour accéder au contenu d’une variable d’environnement, la vue QSYS2.ENVIRONMENT_VARIABLE_INFO est très simple à utiliser :

Dans un programme RPG, il est très simple d’effectuer une lecture SQL.
Mais dans certains cas, nous préférerons utiliser les APIs système : pour la performance, ou dans le CL ! En CL, il est possible d’exécuter une instruction SQL, mais pas de récupérer un result sets (en tout cas pas simplement et avec une bonne performance).
L’appel d’API depuis le CL ne pose pas de soucis, principalement depuis les évolutions permettant de maitriser l’allocation mémoire des variables (variables autonomes, basées sur un pointeur, ou basée sur une autre variable – équivalent OVERLAY du RPG) :

Maintenant, lorsque l’on utilise des API, il est (souvent) nécessaire de passer par des pointeurs, de façon explicite ou non. Par exemple, c’est le cas pour QUSRJOBI même si l’on a pas déclaré de pointeur dans notre programme CL :

En réalité, lors d’un appel de programme ou procédure, les paramètres sont transmis par défaut par référence : concrètement on passe un pointeur sur le début de la valeur, mais pas la valeur elle-même !
Il faut commencer à interpréter les prototypes des API en fonction du langage d’appel …
Le système étant écrit en C, certaines API utilisent la définition C d’une chaine de caractères : un pointeur sur le premier caractère, la fin de la chaîne étant marquée par le premier octet null !
En RPG, nous avons la fonction %str() qui permet de gérer ceci :

En CL, pas de fonction équivalent pour gérer cela.
Prenons par exemple l’API getEnv() (en fait une fonction de la bibliothèque standard C) :

De même, la valeur de retour est un pointeur sur le début de la valeur. La fin se situe au premier octet null rencontré …
Voici un exemple d’appel :

DCL VAR(&SPC_INIT) TYPE(*CHAR) LEN(1) VALUE(X'00')
Cela nous sert à créer la valeur pour l’appel : chaine à terminaison nulle contenant le nom de la variable d’environnement recherchée (ici CLASSPATH) :
CHGVAR &ENVVAR ( 'CLASSPATH' *CAT &SPC_INIT )
Pour décoder la valeur de retour, il nous faut parcourir la valeur reçue jusqu’à trouver la terminaison nulle. On utilise simplement %SCAN pour trouver la position et redécouper :
CHGVAR VAR(&POSNULL) VALUE(%SCAN(&SPC_INIT &ENVVARVAL) - 1 )
CHGVAR &FINALVAL %SUBSTRING(&ENVVARVAL 1 &POSNULL)
Au final, très peu de code à ajouter, mais nécessite une compréhension de la documentation des APIs, des types de données dans les différents langages, et des mécanismes de transmission de paramètres !
Vous connaissez tous, au moins de nom l’extension « code for i » qui vous permet d’éditer vos sources RPGLE dans votre éditeur favori qui est publié par notre Ami Liam Allan
Si voulez en savoir plus une vidéo très bien faite de notre ami de Yvon est disponible sur la chaine youtube de Volubis ici
Mais il existe également des extensions créé par d’autres contributeurs en voici une qui est apparu en 2022 « IBM i Snippets », elle a été créée par Andy Youens.
L’installation est très simple à partir de la gestion des extensions

Le principe de cette extension est de vous proposer des exemples de codes (par exemple des squelettes pour du RPGLE ou CLLE).
Son usage est très simple vous devez saisir « !i » dans votre éditeur favori .

Cette extension bouge beaucoup depuis sa sortie et les dernières contributions sont récentes, n’hésitez pas à proposer des exemples de codes si vous en avez qui soit présentable
Nous pensons qu’il y aura de plus en plus de extensions disponibles pour l’IBMI et une amélioration de celle exitantes extensions existantes, il est donc important d’avoir un œil ce mode de développement , en sachant que les « JEUNNNNES » connaissent déjà cet interface
Vous pouvez désormais mettre des points d’exit pour savoir quand un fichier IFS est ouvert ou fermé
QIBM_QP0L_OBJ_OPEN
QIBM_QP0L_OBJ_CLOSE
le format de data utilisé est le OBOP0100
exemple de programme en CLP
/*-------------------------------------------------------------------*/
/* exit pgm QIBM_QP0L_OBJ_OPEN FMT OBOP0100 */
/* Contrôle ouverture de fichier */
/*-------------------------------------------------------------------*/
pgm (&data &retour)
/* Paramètres */
dcl &data *char 512 /* Variable recue */
dcl &retour *char 4 /* Variable renvoyée */
/* 0 pour OK */
/* 1 pour KO */
/* Variables de travail */
DCL VAR(&USER) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&DATA 1)
DCL VAR(&EXT) TYPE(*CHAR) STG(*DEFINED) LEN(8) +
DEFVAR(&DATA 11)
DCL VAR(&TYPE) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&DATA 23)
DCL VAR(&FLAG) TYPE(*CHAR) STG(*DEFINED) LEN(4) +
DEFVAR(&DATA 28)
DCL VAR(&IDENT) TYPE(*CHAR) STG(*DEFINED) +
LEN(16) DEFVAR(&DATA 33)
DCL VAR(&PATHL) TYPE(*CHAR) STG(*DEFINED) LEN(4) +
DEFVAR(&DATA 49)
DCL VAR(&PATH) TYPE(*CHAR) STG(*DEFINED) +
LEN(256) DEFVAR(&DATA 53)
dcl &len *dec (5 0)
/* Conversion du path UTF16/UCS2 vers CCSID en cours */
CALL PGM(CVTUCS2) PARM((&PATH) (&PATH))
/* Longueur après conversion / 2 car UCS2 = 2 caractères */
chgvar &len (%BIN(&PATHL) / 2)
/*--------------------------------------------*/
/* Ici Votre traitement */
/*--------------------------------------------*/
SNDUSRMSG MSG('Fichier ' *BCAT %SST(&PATH 1 &LEN) +
*BCAT ', ouvert par ' *BCAT &USER) +
MSGTYPE(*INFO)
/*--------------------------------------------*/
/* Validation de la demande 0 pour OK */
/*--------------------------------------------*/
CHGVAR VAR(%BIN(&retour)) VALUE(0)
endpgm
pour l'attachement du programme au point d'exit
ADDEXITPGM EXITPNT(QIBM_QP0L_OBJ_OPEN)
FORMAT(OBOP0100)
PGMNBR(1)
PGM(PLB/PGMIFS)
THDSAFE(*YES)
REPLACE(*NO)
attention à bien mettre le paramètre THDSAFE(*YES)
Remarque :
Le path du fichier est déclaré en UCS2 ci joint un petit programme de conversion en RPGLE , utile si vous avez choisi d’écrire votre programme en CLLE
**free
// Programme de conversion CVTUCS2
// utf16/UCS2 vers ccsid en cours par défaut
Dcl-pi *N ;
I_zon ucs2(256) ; // soit une chaine de 128
O_zon char(256) ;
End-pi ;
O_zon = I_zon ;
*inlr = *on ;
Pour être analysé par le point d’exit vos fichiers doivent avoir l’attribut *RUNEXIT

Pour le mettre sur un fichier
CHGATR OBJ(‘/home/QSECOFR/QPJOBLOG.PDF’) ATR(RUNEXIT) VALUE(YES)

Pour le mettre sur tous les fichiers crées dans votre répertoire
CHGATR OBJ(‘/home/QSECOFR/’) ATR(CRTRUNEXIT) VALUE(YES)

Cette information n’est pas encore disponible dans la vue QSYS2.IFS_OBJECT_STATISTICS




